2009-09-16 2 views
19

Типичная функциональность сокета PHP является синхронной и останавливает поток при ожидании входящих соединений и данных. (например, socket_read и socket_listen)Может ли PHP асинхронно использовать сокеты?

Как мне сделать то же самое асинхронно? поэтому я могу отвечать на данные в полученном данных, а не на опросе данных и т. д.

ответ

18

Yup, вот что socket_set_nonblock() для. Код взаимодействия сокетов должен быть написан по-разному, учитывая особые значения, которые допускают коды ошибок 11, EWOULDBLOCK и 115, EINPROGRESS.

Вот некоторые несколько-придуман пример кода из PHP синхронизации цикла сокет опроса, в соответствии с просьбой:

$buf = ''; 
$done = false; 
do { 
    $chunk = socket_read($sock, 4096); 
    if($chunk === false) { 
     $error = socket_last_error($sock); 
     if($error != 11 && $error != 115) { 
      my_error_handler(socket_strerror($error), $error); 
      $done = true; 
     } 
     break; 
    } elseif($chunk == '') { 
     $done = true; 
     break; 
    } else { 
     $buf .= $chunk; 
    } 
} while(true); 
+0

Что вы имеете в виду по-разному? Можете ли вы показать мне какие-либо образцы кода асинхронных данных, полученных событиями? –

+0

Итак, это синхронно, но не блокирует? Тогда что именно означает неблокирование? –

+3

Нет, он асинхронен и основан на опросе. Код из более крупного механизма опроса. Насколько я знаю, PHP не имеет поддержки для событий ввода-вывода со средой/сигналом, которые вы запрашиваете. Вы достигаете асинхронной связи, используя операции, которые не дожидаются завершения, но немедленно возвращаются с индикативным кодом ошибки, если операция не готова. Подобно чтению в неблокирующем сокете. В C есть много учебных пособий по использованию асинхронного сокета, которые будут рассмотрены в деталях; Поддержка PHP - это всего лишь слой над стандартным материалом C. – chaos

0

AFAIK PHP строго singlethreaded, что означает, что вы не можете сделать это асинхронно, потому что выполнение сценария всегда линейно.

Прошло некоторое время с тех пор, как я это сделал, но, насколько я помню, вы можете только открыть сокет и продолжить выполнение сценария при получении данных.

+0

Даже образец кода хаоса, похоже, подтверждает этот факт. –

+1

PHP предоставляет stream_select для операций сокета async, аналогично posix select(). – karunski

+1

select() синхронно: он просто позволяет узнать, готов ли сокет к чтению/записи. Вы по-прежнему вызываете его из одного потока и блокируете вызов select() вместо read() или write(). –

5

Как мне сделать то же самое асинхронно? так что я могу ответить на данные в случае данных получено, вместо опроса для данных и т.д.

Вам нужно будет выполнить свой сценарий и выдавать stream_select проверить weither есть какие-либо данные, чтобы получить. Обработайте и отправьте данные назад.

5

Термин «асинхронный» часто используется в сетевом программировании. Для ввода/вывода асинхронный часто используется как другое слово для неблокирования. Это означает, что процесс может продолжаться до того, как вызов в сети api завершит передачу.

Для выполнения процесса в целом, асинхронная означает, что несколько команд могут быть вычислены сразу (одновременно.)

Другими словами, асинхронного ввода/вывода не является действительно асинхронным, если несколько потоков не используются, чтобы позволить множественный чтение/запись/прием происходит одновременно - все сокеты должны подождать синхронного неблокирующего вызова, если у него есть данные для чтения/записи или иначе не будут блокироваться, а чтение/запись большого файла может занимать секунды или даже минуты, если не прерывается. Обратите внимание, что для этого потребуется идеальный поток между клиентом и сервером, а сам TCP прервет передачу. Например, загрузка сервера быстрее, чем клиент может загрузить, приведет к блокировке записи.

Так что с жесткой точки зрения PHP не способен выполнять асинхронную сеть, только не блокируя. Короче говоря, прогрессирование процесса прекратится, когда сетевой вызов сможет с пользой читать/писать и т. Д. Однако процесс будет продолжаться, когда вызов не сможет с пользой читать/писать или в противном случае блокируется. В действительно асинхронной системе процесс будет продолжаться независимо, а чтение/запись будет выполняться в другом потоке. Обратите внимание, что блокирование ввода-вывода все равно может выполняться асинхронно, если выполняется в другом потоке.

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

С учетом этого функция выбора по-прежнему допускает истинное неблокирующее поведение в PHP. В C службы опроса имеют потерю производительности по сравнению с управляемым событием, поэтому я уверен, что он будет таким же для PHP. Но эта потеря находится в наносекундах-микросекундах в зависимости от количества сокетов, где время, сохраненное от неблокирующего вызова, обычно составляет миллисекунды или даже секунды, если вызов заставлен ждать.