3

是否有任何方法(除了检查 ping 响应)来检测客户端流(我不知道流是否与套接字有任何不同)变得不可用(即不再有任何连接但没有完全断开连接) )?

使用此代码:

#!/usr/bin/env php
<?php
$socket = stream_socket_server(
    'tcp://192.168.1.1:47700',
    $errno,
    $errstr,
    STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
    stream_context_create(
        array(),
        array()
    )
);
if (!$socket) {
    echo 'Could not listen on socket'."\n";
}
else {
    $clients = array((int)$socket => $socket);
    $last = time();
    while(true) {
        $read = $clients;
        $write = null;
        $ex = null;
        stream_select(
            $read,
            $write,
            $ex,
            5
        );
        foreach ($read as $sock) {
            if ($sock === $socket) {
                echo 'Incoming on master...'."\n";
                $client = stream_socket_accept(
                    $socket,
                    5
                );
                if ($client) {
                    stream_set_timeout($client, 1);
                    $clients[(int)$client] = $client;
                }
            }
            else {
                echo 'Incoming on client '.((int)$sock)."...\n";
                $length = 1400;
                $remaining = $length;

                $buffer = '';
                $metadata['unread_bytes'] = 0;
                do {
                    if (feof($sock)) {
                        break;
                    }

                    $result = fread($sock, $length);

                    if ($result === false) {
                        break;
                    }

                    $buffer .= $result;

                    if (feof($sock)) {
                        break;
                    }

                    $continue = false;

                    if (strlen($result) == $length) {
                        $continue = true;
                    }

                    $metadata = stream_get_meta_data($sock);
                    if ($metadata && isset($metadata['unread_bytes']) && $metadata['unread_bytes']) {
                        $continue = true;
                        $length = $metadata['unread_bytes'];
                    }
                } while ($continue);

                if (strlen($buffer) === 0 || $buffer === false) {
                    echo 'Client disconnected...'."\n";
                    stream_socket_shutdown($sock, STREAM_SHUT_RDWR);
                    unset($clients[(int)$sock]);
                }
                else {
                    echo 'Received: '.$buffer."\n";
                }
                echo 'There are '.(count($clients) - 1).' clients'."\n";
            }

        }
        if ($last < (time() - 5)) {
            foreach ($clients as $id => $client) {
                if ($client !== $socket) {
                    $text = 'Yippee!';
                    $ret = fwrite($client, $text);
                    if ($ret !== strlen($text)) {
                        echo 'There seemed to be an error sending to the client'."\n";
                    }
                }
            }
        }
    }
}
if ($socket) {
    stream_socket_shutdown($socket, STREAM_SHUT_RDWR);
}

和另一台计算机上的套接字客户端,我可以连接到服务器,发送和接收数据,并干净地断开连接,一切都按预期运行。但是,如果我在客户端计算机上拉取网络连接,则在服务器端没有检测到任何东西 - 服务器继续侦听客户端套接字,并且还会写入它而不会出现任何错误。

4

2 回答 2

1

据我了解,调用feof($stream)会告诉您远程套接字是否已断开连接,但我对此并不确定。在继续研究解决方案的同时,我自己也在使用 ping/pong。

于 2019-02-09T08:03:12.563 回答
0

您需要设置套接字超时,在这种情况下,如果客户端没有及时响应,您会收到错误消息。

检查 PHP 的 stream_set_timeout 函数: http ://www.php.net/manual/en/function.stream-set-timeout.php

还要检查socket_set_option:http: //php.net/manual/en/function.socket-set-option.php

最后,查看这篇关于如何在 PHP 中有效使用套接字的精彩文章:“PHP 套接字编程,以正确的方式完成” http://christophh.net/2012/07/24/php-socket-programming/

于 2013-05-23T13:56:43.197 回答