【问题标题】:socket_read unblock in incomming multiple client with socket_acceptsocket_read 在使用 socket_accept 接收多个客户端时解除阻塞
【发布时间】:2015-03-12 16:00:44
【问题描述】:

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

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

我在 socket_accept 中将 socket_set_nonblock 设置为非阻塞我的套接字 这很好用,但对于连接到我的服务器的客户端,我不会阻止客户端

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);

当第二个客户端连接到程序时 echo "do something..." 在第二个客户端输入任何内容之前不会工作 对于非阻塞 socket_read 我必须做什么?不可能还是我使用socket_select不正确?

【问题讨论】:

    标签: php sockets


    【解决方案1】:

    我投入了数小时终于得到了一些工作。 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);
    

    【讨论】:

      猜你喜欢
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 2010-10-25
      相关资源
      最近更新 更多