2013-12-16 2 views
1

Я пишу сервер websocket в PHP, который должен иметь возможность обрабатывать большое количество параллельных подключений. В настоящее время я использую функцию socket_select, чтобы позволить ей обрабатывать их, но это все еще блокирует все другие соединения при отправке большому блоку данных клиенту. Есть ли способ, чтобы мастер-скрипт принимал входящий сокет, а затем запускал второй PHP-скрипт (очевидно, неблокирующий) и передавал клиентский сокет этому сценарию для обработки? Я знаю, что это возможно на C, но кодовая база такова, что миграция невозможна, к сожалению.Передача живого сокета между двумя скриптами PHP

* Сервер работает исключительно в стеке Unix, не требуется решение, совместимое с MS.

+0

Возможно, вы сможете получить эту работу ... однако, вы считаете платформу, где это намного проще сделать, например, Node.js? – Brad

+0

Да, я начинаю думать, что мне придется изменить программу на C, которую я написал давно, чтобы заставить ее работать. Я хочу сказать, что это интересный проект, который я хочу преследовать, но на данный момент у меня нет времени, чтобы ускорить работу сокетов и т. Д. На новом языке и все же в конечном итоге получить безопасное решение. – Chris

ответ

0

Ответ оказывается тем же самым ответом, который вы использовали бы в C - fork(). Когда вы используете fork, состояние всех открытых файлов и портов сохраняется, поэтому дочерний процесс может читать порт, открытый его родителем (это то же самое, что современные веб-серверы отключают рабочие потоки для каждого подключенного клиента) это требует использования pcntl (управления технологическими процессами) модуль, который по умолчанию отключен и должен использоваться экономно, но это работает:

if($verbose) 
    echo "Connected Client from $remoteaddy to $localaddy\n"; 
echo "Forking..."; 
$pid = pcntl_fork(); // you're bringing children into this world, just to kill them in a few seconds. You monster. 
if($pid==0){ 
      $p = posix.getpid(); 
    echo "PID OF CHILD: $p\n"; 
    //in child process. Send a handshake and wait for the callback from the WebSockets library 
    $this->send($client, "Thank you for contacting myAwesomeServer.com! I'm slave #{$p}, and I'll be your host today"); 
}else if($pid>0){ 
    $childWorkers[]=$pid; 
    echo "[ OK ]\n"; 
    $this->disconnect($client->socket, false); //disconnect the clients socket from the master thread, so only the child thread is talking to the client 

}else if($pid==-1){ 
    echo "[FAIL] unable to create child worker\n"; 
} 

ВНИМАНИЕ !! Этот подход ПРАВИЛЬНО АКАДЕМИЧЕСКИЙ, и его следует использовать только в небольших проектах «домашних животных», когда у вас недостаточно времени для изучения более подходящего языка (лично я знаю C достаточно хорошо для fork(), но у меня недостаток знаний его функций манипуляции с строкой, несомненно, оставят на сервере уязвимое отверстие безопасности). Я не уверен, как двигатель Zend делает это pcntl_fork(), но я бы себе представить, что образ памяти этого уродства будет много раз размер эквивалентного кода C ..

0

Я m, в настоящее время использующий функцию socket_select, чтобы позволить ему обрабатывать их, но при этом по-прежнему блокируется все другие соединения при отправке большому блоку данных клиенту.

Тогда не отправляйте все данные за один раз. Если вы собираетесь сделать

socket_write ($mysocket, $mybuffer, 10000000); 

тогда да, вам придется подождать, пока все 10 миллионов байт не были отправлены. Тем не менее, вы можете использовать массив $writesocket_select, чтобы проверить, можете ли вы записать его в сокет в сочетании с неблокирующими сокетами. Каждый раз, когда socket_select говорит, что у вас есть «go!» на сокете, напишите данные, пока socket_write не начнет жаловаться (т. е. возвращает FALSE или меньше указанной длины). Это обеспечит оптимальное заполнение буфера отправки сокета.

Недостатком является то, что вы должны отслеживать, где именно находится ваш выходной буфер; также отключите неблокирование в сокете после того, как вы написали все ваши данные, или socket_select продолжит стрельбу (предполагается, что вы хотите отправить несколько больших капель данных).

Смежные вопросы