当前位置: 首页> 最新文章列表> socket_accept() + stream_socket_client(): 服务端与客户端通信全流程

socket_accept() + stream_socket_client(): 服务端与客户端通信全流程

M66 2025-05-18

在PHP中,基于Socket的网络通信是一种非常底层且灵活的通信方式,适用于实现自定义协议或需要高性能通信的场景。本文将结合socket_accept()stream_socket_client()两个函数,演示如何实现一个简单的服务端与客户端的完整通信流程。

1. 基础知识简介

  • socket_accept():用于接受服务端socket上的客户端连接请求,返回一个新的socket资源,表示客户端连接。

  • stream_socket_client():用于创建客户端连接,连接到指定服务器的socket。

服务端负责监听端口,接受连接请求;客户端发起连接请求,连接到服务端。双方建立连接后即可进行数据交换。

2. 服务端示例代码

<?php
// 创建TCP socket服务端,监听指定端口
$host = '0.0.0.0';  // 监听所有IP
$port = 12345;

// 创建socket资源
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) {
    die("创建socket失败: " . socket_strerror(socket_last_error()));
}

// 绑定IP和端口
if (!socket_bind($socket, $host, $port)) {
    die("绑定socket失败: " . socket_strerror(socket_last_error($socket)));
}

// 开始监听
if (!socket_listen($socket, 5)) {
    die("监听socket失败: " . socket_strerror(socket_last_error($socket)));
}

echo "服务端启动,监听 {$host}:{$port}\n";

while (true) {
    // 接受客户端连接
    $clientSocket = socket_accept($socket);
    if ($clientSocket === false) {
        echo "接受连接失败: " . socket_strerror(socket_last_error($socket)) . "\n";
        continue;
    }

    // 读取客户端发送的数据
    $input = socket_read($clientSocket, 1024);
    echo "收到客户端消息: " . trim($input) . "\n";

    // 向客户端发送响应
    $response = "服务器收到消息:" . $input;
    socket_write($clientSocket, $response, strlen($response));

    // 关闭客户端连接
    socket_close($clientSocket);
}

socket_close($socket);

3. 客户端示例代码

<?php
$host = 'm66.net';  // 替换成题目要求的域名
$port = 12345;

// 创建客户端socket连接
$client = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 5);
if (!$client) {
    die("连接服务器失败: $errstr ($errno)\n");
}

// 向服务端发送数据
$message = "你好,服务端!";
fwrite($client, $message);

// 读取服务端响应
$response = fread($client, 1024);
echo "服务端响应: " . trim($response) . "\n";

// 关闭连接
fclose($client);

4. 流程解析

  1. 服务端

    • 使用socket_create()创建socket资源。

    • 绑定IP和端口后,调用socket_listen()监听客户端连接。

    • 使用socket_accept()阻塞等待客户端连接。

    • 连接建立后,使用socket_read()接收客户端数据,socket_write()发送响应。

    • 完成通信后关闭客户端socket,继续等待下一个连接。

  2. 客户端

    • 使用stream_socket_client()连接服务端。

    • 连接成功后,向服务端发送消息。

    • 读取服务端返回的数据,完成一次完整的请求-响应流程。

    • 关闭连接。


5. 注意事项

  • 服务端使用的是socket_*系列函数,客户端使用的是stream_socket_client(),这两者在底层都操作socket资源,但接口风格不同,示例结合使用主要是为了展示PHP常见的socket用法。

  • 生产环境中,应对socket读写加入错误处理和超时控制,避免死循环或阻塞。

  • 如果服务端部署在云服务器或内网,需确保端口开放,且域名m66.net解析正确指向服务端IP。

  • 服务端socket_accept()是阻塞调用,适合单连接示例,实际项目中可结合多线程、多进程或异步IO进行优化。