PHP SocketServer не принимает более 255 одновременных подключений
Я использую скрипт PHP (5.4.12) на компьютере с Windows Server 2008. Когда общее количество одновременных подключений достигло 255, скрипт завершился сбоем.
В системе PHP 5.2.x SocketServer завершается с ошибкой: "Была предпринята попытка выполнить что-то, что не является сокетом".
PHP 5.4.12, не дает сбоя, но больше не обрабатывает соединения.
Я использую следующий код, взятый с сайта PHP.net: http://php.net/manual/en/sockets.examples.php
<?php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$address = '192.168.1.7';
$port = 8676;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
echo "socket_create() last error " . socket_strerror(socket_last_error()) . "\n";
}
if (socket_bind($sock, $address, $port) === false) {
echo "socket_bind() last error " . socket_strerror(socket_last_error($sock)) . "\n";
}
if (socket_listen($sock, 5) === false) {
echo "socket_listen() last error " . socket_strerror(socket_last_error($sock)) . "\n";
}
$clients = array();
do {
$read = array();
$read[] = $sock;
$read = array_merge($read,$clients);
$write = NULL;
$except = NULL;
if(socket_select($read,$write , $except , $tv_sec = 5)===false)
{
echo(PHP_EOL.'\n\ncrash\n\n'.PHP_EOL);
exit();
}
if (in_array($sock, $read)) {
if (($msgsock = socket_accept($sock)) === false) {
echo "socket_accept() falló: razón: " . socket_strerror(socket_last_error($sock)) . "\n";
// break;
}
$clients[] = $msgsock;
$key = array_keys($clients, $msgsock);
$msg = "{$key[0]} welcome msg\n".PHP_EOL;
socket_write($msgsock, $msg, strlen($msg));
}
// Handle Input
foreach ($clients as $key => $client) { // for each client
if (in_array($client, $read)) {
if (false === ($buf = socket_read($client, 2048))) {
echo "socket_read() last error: " . socket_strerror(socket_last_error($client)) . "\n";
// break 2;
}
if (!$buf = trim($buf)) {
continue;
}
if ($buf == 'quit') {
$talkback = print_r($clients);
socket_write($client, $talkback, strlen($talkback));
unset($clients[$key]);
socket_close($client);
break;
}
if ($buf == 'shutdown') {
socket_close($client);
break 2;
}
$talkback = "Client {$key}: Echo: '$buf'.\n";
socket_write($client, $talkback, strlen($talkback));
echo "$buf\n";
}
}
} while (true);
socket_close($sock);
?>
Я протестировал скрипт, запустив "EchoServerTest.exe". Я создаю несколько одновременных соединений.
Сначала я подумал, что это проблема в WinSock, но я не могу обнаружить, что существует ограничение на 255 соединений с WinSock.
Я также изменил настройки реестра TcpNumConnections, TcpTimedWaitDelay и MaxUserPort.
Я использовал тот же код на сервере Ubuntu, поэтому проблема была связана с Windows. Я проверил это на двух разных серверах, оба Windows Server 2008 (32-разрядный и 64-разрядный). Один локально и один в интернете. Таким образом, брандмауэр или другие внешние проблемы должны быть исключены.
У меня нет вариантов.
Прежде чем спросить, тебе действительно нужно так много связей? Да. Есть много "мертвых" соединений, поэтому я изменил код. Теперь эти "мёртвые" соединения теперь "Тайм-аут". Поэтому у меня есть время, чтобы решить эту проблему, но со временем количество одновременных подключений снова достигнет 255.
Есть идеи на этот счет?
1 ответ
Я думаю, что проблема в этой строке:
if (socket_listen($sock, 5) === false) {
Вы вручную ограничиваете 5 количеством невыполненных входящих соединений, поставленных в очередь на обработку. В Linux это молча обрезается до SOMAXCONN
В Windows это не так. Попробуйте использовать SOMAXCONN
вместо 5.