ZetCode

PHP fsockopen 函数

最后修改于 2025 年 4 月 4 日

PHP fsockopen 函数打开一个网络套接字连接。它支持使用各种协议进行低级网络通信。

基本定义

fsockopen 启动与指定主机的套接字连接。它适用于 IPv4 和 IPv6 地址的 TCP/IP 套接字。

语法:fsockopen(string $hostname, int $port, int &$errno, string &$errstr, float $timeout = ini_get("default_socket_timeout")): resource|false。成功时返回文件指针,失败时返回 false。

基本 HTTP 请求

此示例演示如何使用 fsockopen 发出简单的 HTTP GET 请求。

http_request.php
<?php

declare(strict_types=1);

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);

if (!$fp) {
    echo "Error: $errstr ($errno)";
} else {
    $out = "GET / HTTP/1.1\r\n";
    $out .= "Host: www.example.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    
    fwrite($fp, $out);
    while (!feof($fp)) {
        echo fgets($fp, 128);
    }
    fclose($fp);
}

这会连接到 example.com 的 80 端口(HTTP),发送一个 GET 请求,并读取响应。连接在之后被正确关闭。

SMTP 邮件发送

这展示了如何使用原始套接字通信通过 SMTP 发送电子邮件。

smtp_email.php
<?php

declare(strict_types=1);

$smtp = fsockopen("smtp.example.com", 25, $errno, $errstr, 30);

if (!$smtp) {
    die("Error: $errstr ($errno)");
}

$commands = [
    "EHLO localhost\r\n",
    "MAIL FROM: <sender@example.com>\r\n",
    "RCPT TO: <recipient@example.com>\r\n",
    "DATA\r\n",
    "Subject: Test\r\n\r\nHello World\r\n.\r\n",
    "QUIT\r\n"
];

foreach ($commands as $cmd) {
    fwrite($smtp, $cmd);
    echo fgets($smtp, 256);
}

fclose($smtp);

这连接到 SMTP 服务器,并通过直接发出 SMTP 命令来发送基本电子邮件。每个命令都会收到来自服务器的响应。

端口扫描器

此示例创建一个简单的端口扫描器来检查主机上的开放端口。

port_scanner.php
<?php

declare(strict_types=1);

function scanPort($host, $port, $timeout = 1) {
    $fp = @fsockopen($host, $port, $errno, $errstr, $timeout);
    if ($fp) {
        fclose($fp);
        return true;
    }
    return false;
}

$host = "example.com";
$ports = [21, 22, 25, 80, 443];

foreach ($ports as $port) {
    $status = scanPort($host, $port) ? "open" : "closed";
    echo "Port $port is $status\n";
}

该函数尝试使用短超时时间连接到每个端口。如果连接成功,则端口已打开。这是一个基本的安全工具。

自定义 TCP 客户端

这演示了一个自定义 TCP 客户端,用于发送和接收数据。

tcp_client.php
<?php

declare(strict_types=1);

$socket = fsockopen("tcp://127.0.0.1", 9000, $errno, $errstr, 30);

if (!$socket) {
    die("Error: $errstr ($errno)");
}

fwrite($socket, "Hello Server!\n");
echo "Server says: " . fgets($socket, 1024);

fclose($socket);

这连接到本地 TCP 服务器的 9000 端口,发送一条消息,并读取响应。适用于自定义协议的实现。

HTTPS 连接

这展示了如何使用 fsockopen 建立安全的 HTTPS 连接。

https_request.php
<?php

declare(strict_types=1);

$host = "www.example.com";
$port = 443;
$timeout = 30;

$fp = fsockopen("ssl://$host", $port, $errno, $errstr, $timeout);

if (!$fp) {
    die("Error: $errstr ($errno)");
}

$out = "GET / HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";

fwrite($fp, $out);
while (!feof($fp)) {
    echo fgets($fp, 128);
}
fclose($fp);

这使用 ssl:// 协议前缀连接到 443 端口 (HTTPS)。其余部分的工作方式类似于 HTTP,但使用加密的传输层安全性。

最佳实践

来源

PHP fsockopen 文档

本教程涵盖了 PHP fsockopen 函数,并提供了各种网络通信场景的实用示例。

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出 所有 PHP 网络函数