我正试图习惯于用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循环的迭代次数,则一些消息会找到到达服务器的方式,但不是全部。
现在我的主要问题:如何确保在所有消息发送完毕之前客户端不会停止执行?
我已经有了一些想法,但我不知道最佳解决方案是什么。