客户端在服务器收到所有消息之前断开连接

时间:2019-01-08 20:44:46

标签: php sockets

我正试图习惯于用PHP进行套接字编程(这只是为了学习)。我已经写了一个简单的回显服务器,它似乎可以正常工作(用PuTTY测试)。我的问题只在客户端。
这是到目前为止我得到的(尚无错误处理,请多多包涵):

server.php

$host = '127.0.0.1';
$port = 10000;
$null = null;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_set_nonblock($socket);
socket_bind($socket, $host, $port);
socket_listen($socket);

echo("[Listening...]\r\n");

$client_list = [$socket];

while(true) {
    $changed_clients = $client_list;

    $select = socket_select($changed_clients, $null, $null, 0, 10);
    if($select < 1) {
        continue;
    }

    if(in_array($socket, $changed_clients)) {
        $client_list[] = $new_client = socket_accept($socket);
        $msg = "Welcome to the server!\r\n";
        socket_write($new_client, $msg, strlen($msg));
        socket_getpeername($new_client, $ip);
        echo("[New client has connected: " . $ip . "]\r\n");
    }

    foreach($client_list as $client) {
        if($client !== $socket) {   // ignore server socket
            $msg = @socket_read($client, 4096, PHP_NORMAL_READ);

            if($msg === false) { // client disconnected
                socket_getpeername($client, $ip);
                $key = array_search($client, $client_list);
                unset($client_list[$key]);
                echo("[Client " . $ip . " disconnected]\r\n");
                continue; // next client
            }

            $msg = trim($msg);
            if(!empty($msg)) {
                if($msg == "shutdown") {
                    echo("[Shutting down...]\r\n");
                    break 2;
                }
                if($msg == "quit") {
                    echo("[Disconnecting client...]\r\n");
                    socket_close($client);
                    $key = array_search($client, $client_list);
                    unset($client_list[$key]);
                    continue;
                }

                socket_getpeername($new_client, $ip);
                $msg = $ip . ": " . $msg . "\r\n";
                echo($msg);
                foreach($client_list as $send_socket) {
                    if($send_socket === $socket) {
                        continue;
                    }
                    socket_send($send_socket, $msg, strlen($msg), 0);
                }
            }
        }
    }
}

socket_close($socket);

client.php

error_reporting (E_ALL);

$host = '127.0.0.1';
$port = 10000;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_connect($socket, $host, $port);

for($i = 0; $i<10; $i++) {
    $msg = "Test " . $i . "\r\n";
    socket_write($socket, $msg, strlen($msg)); 
}

socket_close($socket);

所需的server.php输出:

[Listening...]
[New client has connected: 127.0.0.1]
127.0.0.1: Test 0
127.0.0.1: Test 1
127.0.0.1: Test 2
127.0.0.1: Test 3
127.0.0.1: Test 4
127.0.0.1: Test 5
127.0.0.1: Test 6
127.0.0.1: Test 7
127.0.0.1: Test 8
127.0.0.1: Test 9
[Client 127.0.0.1 disconnected]

实际输出:

[Listening...]
[New client has connected: 127.0.0.1]
[Client 127.0.0.1 disconnected]

我已经弄清问题所在,即client.php脚本在服务器读取消息之前(使用socket_read)完成了其执行。如果我增加了客户端脚本中for循环的迭代次数,则一些消息会找到到达服务器的方式,但不是全部。

现在我的主要问题:如何确保在所有消息发送完毕之前客户端不会停止执行?
我已经有了一些想法,但我不知道最佳解决方案是什么。

0 个答案:

没有答案