本地Socket数据分发至多进程失败:Broken Pipe错误求助
问题描述
- 核心需求:主进程维持IRC服务器的长连接,通过Socket将获取到的数据分发给多个本地子进程;子进程可按需启停、编辑,仅需读取数据,无需向主进程回传或做安全验证。
- 当前问题:测试脚本运行时触发错误:
PHP Warning: socket_write(): unable to write to socket [32]: Broken pipe
错误原因
你的发送脚本逻辑存在核心错误:socket_listen调用后,直接往监听套接字上写数据,但监听套接字的作用仅为接受新客户端连接,不能直接用于数据收发。同时原逻辑未处理客户端连接,也无法支持多客户端同时接收数据,导致出现管道断裂错误。
修正后的主进程(数据发送端)脚本
$socket = socket_create(AF_INET, SOCK_STREAM, 0); socket_bind($socket, "127.0.0.1", 12340); socket_listen($socket); // 设置非阻塞模式,避免accept操作阻塞主循环 socket_set_nonblock($socket); // 存储所有已建立连接的客户端套接字 $clients = []; while (!file_exists("stop.running")) { // 接受新的客户端连接 if ($newClient = socket_accept($socket)) { $clients[] = $newClient; echo "新客户端已连接\n"; } // 生成测试数据(实际场景替换为IRC获取的真实数据) $message = time() . " " . rand(0, 100) . "\n"; echo "$message<br>"; // 向所有在线客户端广播数据 foreach ($clients as $key => $client) { // 检查客户端连接状态 $error = null; socket_get_option($client, SOL_SOCKET, SO_ERROR, $error); if ($error !== 0 || !socket_write($client, $message)) { // 连接失效,关闭并移除该客户端 socket_close($client); unset($clients[$key]); } } sleep(10); } // 脚本停止时关闭所有连接 foreach ($clients as $client) { socket_close($client); } socket_close($socket);
修正后的子进程(数据接收端)脚本
$server = fsockopen("127.0.0.1", 12340); if (!$server) { die("CANNOT CONNECT"); } // 保持阻塞模式,等待数据到来 stream_set_blocking($server, true); while (!feof($server)) { $buffer = fgets($server, 2048); if ($buffer) { echo $buffer . "<br>"; } } fclose($server);
关键说明
- 主进程通过
socket_accept接收新客户端,维护客户端列表,每次循环向所有在线客户端广播数据 - 主进程设置非阻塞模式,避免因等待新连接而中断数据发送逻辑
- 每次发送前检查客户端连接状态,自动移除失效连接,从根源避免Broken pipe错误
- 子进程逻辑保持简洁,连接后持续读取数据即可,断开后可直接重启重新连接
内容的提问来源于stack exchange,提问作者Zoe Ballz
相关产品推荐
相关产品推荐

