php - socket_read在使用socket_accept传入多个客户端时解除阻止

标签 php sockets

我有客户端可以连接到我的服务器套接字,像这样在套接字中读写

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, $address, $port))
socket_listen($socket);
socket_set_nonblock($socket);

我将socket_set_nonblock设置为在socket_accept中不阻塞我的套接字
这项工作很好,但是对于连接到我的服务器的客户端,我不是非阻塞客户端
while(true){
    if (($newc = @socket_accept($socket)) !== false) {
        //socket_set_nonblock($newc);
        //socket_set_option($socket,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0));
        $clients[] = $newc;
        $data = socket_read($newc, 1024, PHP_NORMAL_READ);
    }
    echo "do sometings ...";
}

我测试了socket_set_nonblock($ newc)和选项SO_RCVTIMEO以防止在socket_read中阻止$ newc,但是我未能成功取消阻止

我像下面那样测试socket_select,但这不起作用
 $write = array();
 $expect = NULL;
 socket_select($clients, $write, $except, 0);

当第二个客户端连接到程序时,回显“做某事...” 在第二个客户端输入任何内容之前不起作用
对于非阻塞的socket_read我该怎么办?这是不可能的,还是我使用的socket_select不正确?

最佳答案

我花了几个小时才终于使工作正常。 socket_set_nonblock($ newsock);每个收入客户对于Linux(CentOS)PHP7都是必需的,但它应在Windows PHP5上运行。

<?php
ini_set('error_reporting', E_ALL ^ E_NOTICE);
ini_set('display_errors', 1);
// Set time limit to indefinite execution
set_time_limit(0);
// Set the ip and port we will listen on
$address = '127.0.0.1';
$port = 6901;
ob_implicit_flush();
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);
// Non block socket type
socket_set_nonblock($sock);
// Clients
$clients = [];
// Loop continuously
while (true) {
    // Accept new connections
    if ($newsock = socket_accept($sock)) {
        if (is_resource($newsock)) {
            // Write something back to the user
            socket_write($newsock, ">", 1).chr(0);
            // Non bloco for the new connection
            socket_set_nonblock($newsock);
            // Do something on the server side
            echo "New client connected\n";
            // Append the new connection to the clients array
            $clients[] = $newsock;
        }
    }
    // Polling for new messages
    if (count($clients)) {
        foreach ($clients AS $k => $v) {
            // Check for new messages
            $string = '';
            if ($char = socket_read($v, 1024)) {
                $string .= $char;
            }
            // New string for a connection
            if ($string) {
                echo "$k:$string\n";
            } else {
                if ($seconds > 60) {
                    // Ping every 5 seconds for live connections
                    if (false === socket_write($v, 'PING')) {
                        // Close non-responsive connection
                        session_close($clients[$k]);
                        // Remove from active connections array
                        unset($clients[$k]);
                    }
                    // Reset counter
                    $seconds = 0;
                }
            }
        }
    }
    sleep(1);
    $seconds++;
}
// Close the master sockets
socket_close($sock);

关于php - socket_read在使用socket_accept传入多个客户端时解除阻止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27943458/

相关文章:

php - 尝试对YouTube标记的RSS供稿进行排序,以对其进行排序(观看次数)

sockets - UDP 中的通信协议(protocol)

java - 如何使用 Eclipse 在 Java 中编译这个网络套接字示例?

php - 在 REST API 中处理 "search"的最佳方法是什么?斯芬克斯呢?

php 记录随机用户名和密码?

c - execl 在服务器端的 while(1) 循环中不起作用; C脚本

java - 套接字读取线不阻塞

java - 加快我的 Java tcp 传输速度!

php - 即使 file_exists() 声明文件存在,require() 也会失败

php - 使用来自第三个表的共享 id 使用来自另一个表的数据更新具有空列的表