按下回车键跳到正文

PHP Socket 实现 TCP、UDP 报文的发送与接收

Contents
  1. PHP Socket TCP 发送数据示例
  2. PHP Socket TCP 接收数据示例
  3. PHP Socket UDP 发送数据示例
  4. PHP Socket UDP 接收数据示例
  5. PHP Socket 相关函数

利用 PHP Socket 相关函数实现 TCP、UDP 端口监听。

需要注意,下面的示例代码中没有处理 Socket 错误。实际应用场景中每一步 Socket 的连接、写入、读取都需要进行错误判断和处理,相应的函数 socket_connect、socket_write、socket_read 以及 socket_bind、socket_listen 返回 false 时,需要调用 socket_last_error() 获取最新的 socket 错误号 $errno,并通过 socket_strerror($errno) 获取错误号对应的能够阅读的错误描述信息。

PHP Socket TCP 发送数据示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$host = '127.0.0.1';
$port = '81';
$message = 'Hello TCP Server';
function send_tcp_message($host, $port, $message)
{
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    @socket_connect($socket, $host, $port);
    $num = 0;
    $length = strlen($message);
    do
    {
        $buffer = substr($message, $num);
        $ret = @socket_write($socket, $buffer);
        $num += $ret;
    } while ($num < $length);
    $ret = '';
    do
    {
        $buffer = @socket_read($socket, 1024, PHP_BINARY_READ);
        $ret .= $buffer;
    } while (strlen($buffer) == 1024);
    socket_close($socket);
    return $ret;
}
$ret = send_tcp_message($host, $port, $message);

PHP Socket TCP 接收数据示例

创建一个 Server 接收 TCP 连接,需要先监听一个端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
$host = '127.0.0.1';
$port = '81';
$callback = 'echo';
function receive_tcp_message($host, $port, $callback)
{
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    // socket_bind() 的参数 $host 必传, 由于是监听本机, 此处可以固定写本机地址
    // 注意: 监听本机地址和内网地址效果不一样
    @socket_bind($socket, $host, $port);
    @set_time_limit(0);
    // 绑定端口之后调用监听函数, 实现端口监听
    @socket_listen($socket, 5);
    // 接下来只需要一直读取, 检查是否有来源连接即可, 如果有, 则会得到一个新的 socket 资源
    while ($child = @socket_accept($socket))
    {
        // 休息 1 ms, 也可以不用休息
        usleep(1000);
        if (false === socket_getpeername($child, $remote_host, $remote_port))
        {
            @socket_close($child);
            continue;
        }
        // 读取请求数据
        // 例如是 http 报文, 则解析 http 报文
        $request = '';
        do
        {
            $buffer = @socket_read($child, 1024, PHP_BINARY_READ);
            if (false === $buffer)
            {
                @socket_close($child);
                continue 2;
            }
            $request .= $buffer;
        } while (strlen($buffer) == 1024);
        // 此处省略如何调用 $callback
        $response = $callback($remote_host, $remote_port, $request);
        if (!strlen($response))
        {
            // 至少返回含有一个空格的字符串
            $response = ' ';
        }
        // 因为是 TCP 链接, 需要返回给客户端处理数据
        $num = 0;
        $length = strlen($response);
        do
        {
            $buffer = substr($response, $num);
            $ret = @socket_write($child, $buffer);
            $num += $ret;
        } while ($num < $length);
        // 关闭 socket 资源, 继续循环
        @socket_close($child);
    }
}
// 客户端来的任何请求都会打印到屏幕上
receive_tcp_message($host, $port, $callback);
// 如果程序没有出现异常,该进程会一直存在

有一个快捷的函数 socket_create_listen($port),创建、绑定、监听一步到位。

PHP Socket UDP 发送数据示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$host = '127.0.0.1';
$port = '82';
$message = 'Hello UDP Server';
function send_udp_message($host, $port, $message)
{
    $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    @socket_connect($socket, $host, $port);
    $num = 0;
    $length = strlen($message);
    do
    {
        $buffer = substr($message, $num);
        $ret = @socket_write($socket, $buffer);
        $num += $ret;
    } while ($num < $length);
    socket_close($socket);
    // UDP 是一种无链接的传输层协议, 不需要也无法获取返回消息
    return true;
}
send_udp_message($host, $port, $message);

PHP Socket UDP 接收数据示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$host = '127.0.0.1';
$port = '82';
$callback = 'echo';
function receive_udp_message($host, $port, $callback)
{
    $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    @socket_bind($socket, $host, $port);
    @set_time_limit(0);
    while (true)
    {
        usleep(1000);
        $ret = @socket_recvfrom($socket, $request, 16384, 0, $remote_host, $remote_port);
        if ($ret)
        {
            $callback($remote_host, $remote_port, $request);
        }
        // 不需要返回给客户端任何消息, 继续循环
    }
}
// 客户端来的任何请求都会打印到屏幕上
receive_udp_message($host, $port, $callback);
// 如果程序没有出现异常,该进程会一直存在

PHP Socket 相关函数

  1. socket_accept — Accepts a connection on a socket
  2. socket_bind — Binds a name to a socket
  3. socket_clear_error — Clears the error on the socket or the last error code
  4. socket_close — Closes a socket resource
  5. socket_cmsg_space — Calculate message buffer size
  6. socket_connect — Initiates a connection on a socket
  7. socket_create_listen — Opens a socket on port to accept connections
  8. socket_create_pair — Creates a pair of indistinguishable sockets and stores them in an array
  9. socket_create — Create a socket (endpoint for communication)
  10. socket_get_option — Gets socket options for the socket
  11. socket_getpeername — Queries the remote side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
  12. socket_getsockname — Queries the local side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
  13. socket_import_stream — Import a stream
  14. socket_last_error — Returns the last error on the socket
  15. socket_listen — Listens for a connection on a socket
  16. socket_read — Reads a maximum of length bytes from a socket
  17. socket_recv — Receives data from a connected socket
  18. socket_recvfrom — Receives data from a socket whether or not it is connection-oriented
  19. socket_recvmsg — Read a message
  20. socket_select — Runs the select() system call on the given arrays of sockets with a specified timeout
  21. socket_send — Sends data to a connected socket
  22. socket_sendmsg — Send a message
  23. socket_sendto — Sends a message to a socket, whether it is connected or not
  24. socket_set_block — Sets blocking mode on a socket resource
  25. socket_set_nonblock — Sets nonblocking mode for file descriptor fd
  26. socket_set_option — Sets socket options for the socket
  27. socket_shutdown — Shuts down a socket for receiving, sending, or both
  28. socket_strerror — Return a string describing a socket error
  29. socket_write — Write to a socket

From LzSkyline's Blog : https://www.lzskyline.com/archives/256

3 条评论

  1. Xewrtyuoipye
    Xewrtyuoipye 2016-11-19

    Xighefjeo orj wokwp dkow pwk wodj d hfdgfhgf 4756 5uhtyjur urt45

  2. Ahsgdfloqifg
    Ahsgdfloqifg 2016-11-19

    Pgksrjgiohi hw hweokfjeq ojfe jfweiogwo gwoj wijf gdhgtrj575 y6u75tyhgf 5yu5regr

  3. Iopafeopt
    Iopafeopt 2016-11-20

    Ugireojfe whfiwehfjwehwhfjehfwefhweh 777uiop fweh iwehf weiohf wieohf iwehf iweyu59tu328hfire iuwfodhqw934785 h3urh9wjfwgut h9wh9889wh98r h4wt93qrj29th2 rj2ghw9tfq.

发表评论

电子邮件地址不会被公开。 必填项已用*标注