确定客户端是否已使用套接字关闭了与服务器的连接


determine if client has closed connection to server using socket

我正在尝试检查客户端是否已断开连接,以便关闭客户端连接,允许客户端重新连接。

我有以下内容。

$socket = @socket_create_listen("12345");
while (true) {  
    $client = socket_accept($socket);
    socket_write($client, 'hello');
    while (true) {
        //Code to exit this loop when client looses connection
        socket_write($client, '');
        echo socket_last_error($socket);
    }
    socket_close($client);  
}

尝试:

[1] 向客户端写入一个空字符串,希望这会在客户端断开连接时产生错误,但这不起作用。

[2] 使用ocket_select

$r = array($socket);
$w = NULL;
$e = NULL;
if (false === socket_select($r, $w, $e, 0)) {
    echo "socket_select() failed, reason: " .
        socket_strerror(socket_last_error()) . "'n";
}

这似乎也没有产生错误,然后客户端失去了连接。

注意:我试图在服务器端完成这项工作,因此发送一点并等待回复并不是我真正想要的。通常情况下,我只是向客户端写入而不接收数据,因此在阻塞中运行代码并不是问题,因为我通常是在写而不是在读。

以下是一些我认为可以用来检测退出套接字的代码。。。

该代码的创建者被称为Andrew Gillard没有其他许可证信息可用。。。

<?php
$host = '127.0.0.1';
$port = 7010;
gc_enable();
set_time_limit(0);
function socketError($errorFunction, $die=false)
{
    $errMsg = socket_strerror(socket_last_error());
    echo $errorFunction.' '.$errMsg."'n";
    if ($die) die("Program Ended'n");
}
//Attempt to create our socket. The "@" hides PHP's standard error reporting,
if (!($server = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) socketError('socket_create', true);
//socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
if (!@socket_bind($server, $host, $port)) socketError('socket_bind', true);
if (!@socket_listen($server)) socketError('socket_listen', true);
 //Create an array to store our sockets in. We use this so that we can
// determine which socket has new incoming data with the "socket_select()"
// function, and to properly close each socket when the script finishes
$allSockets = array($server);
while (true) {
    //We have to echo something to the browser or PHP won't know if the Stop button has been pressed
    //echo ' ';
    //if ( connection_aborted() ) {
        //The Stop button has been pressed, so close all our sockets and exit
        //foreach ($allSockets as $socket) socket_close($socket);
        //break;
    //}
    //socket_select() is slightly strange. You have to make a copy of the array
    // of sockets you pass to it, because it changes that array when it returns
    // and the resulting array will only contain sockets with waiting data on
    // them. $write and $except are set to NULL because we aren't interested in
    // them. The last parameter indicates that socket_select will return after
    // that many seconds if no data is receiveed in that time; this prevents the
    // script hanging forever at this point (remember, we might want to accept a
    // new connection or even exit entirely) and also pauses the script briefly
    // to prevent this tight while() loop using a lot of processor time
    $changedSockets = $allSockets;
    @socket_select($changedSockets, $write = NULL, $except = NULL, 10);
    //Now we loop over each of the sockets that socket_select() says have new
    // data on them
    foreach($changedSockets as $socket) {
        if ($socket == $server) {
            //socket_select() will include our server socket in the
            // $changedSockets array if there is an incoming connection attempt
            // on it. This will only accept one incoming connection per while()
            // loop iteration, but that shouldn't be a problem given the
            // frequency that we're iterating
            if (!($client = @socket_accept($server))) {
                socketError('socket_accept', false);
            } else {
                //Accepted incoming connection, add new client socket to our array of sockets
                @socket_set_nonblock($client);
                $allSockets[] = $client;
            }
            echo "Accepted: allSockets count = ".count($allSockets)." memory: ".memory_get_usage()."'n";
        } else {
            //Attempt to read data from this socket
            echo "socket read start'n"; //DEBUG
            $data = @socket_read($socket, 1024);
            echo "socket read end'n"; //DEBUG
            if ($data === false || $data === '') {
                //socket_read() returned FALSE, meaning that the client has
                // closed the connection. Therefore we need to remove this
                // socket from our client sockets array and close the socket
                //A potential bug in PHP means that socket_read() will return
                // an empty string instead of FALSE when the connection has
                // been closed, contrary to what the documentation states. As
                // such, we look for FALSE or an empty string (an empty string
                // for the current, buggy, behaviour, and FALSE in case it ends
                // up getting fixed at some point)
                unset($allSockets[array_search($socket, $allSockets)]);
                @socket_close($socket);
                echo "$socket closed, number left = ".count($allSockets)."'n";
            } else {
                //We got useful data from socket_read()
                echo "$socket [".count($allSockets)." - ".memory_get_usage(). "] wrote: $data'n";
                // ADD YOUR DATA HANDLER HERE
            }
        }
    }
} // end while
?>

我遇到了同样的问题,下面是我如何解决的:

$result = socket_read($socket,2000);
if ($result === "") {
      // it goes in here when the socket (host) has disconnected
}
else {
     // it goes in here when the buffer is empty or the buffer has data in it
}