Я пытаюсь привыкнуть к программированию сокетов в 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 в клиентском скрипте, некоторые сообщения найдут свой путь на сервер, но не все.
Теперь мой главный вопрос: Как я могу убедиться, что клиент не прекращает выполнение до того, как все сообщения были отправлены?
У меня уже есть некоторые идеи, но я не знаю, какое будет лучшее решение.