Может ли PHP асинхронно использовать сокеты?
Типичная функциональность сокета PHP является синхронной и останавливает поток при ожидании входящих соединений и данных. (например, socket_read
и socket_listen
)
Как сделать то же самое асинхронно? поэтому я могу отвечать на данные в полученном данных, вместо опроса для данных и т.д.
Ответы
Ответ 1
Yup, для чего socket_set_nonblock()
. Предположим, что код взаимодействия сокетов должен быть написан по-разному, учитывая особые значения, которые допускают коды ошибок 11, EWOULDBLOCK
и 115, EINPROGRESS
.
Вот какой-то несколько вымышленный пример кода из цикла опроса сокетов PHP sync, по запросу:
$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);
Ответ 2
Как сделать то же самое асинхронно? поэтому я могу реагировать на данные в данных полученное событие, вместо опроса для данные и т.д.
Вам нужно будет выполнить ваш script и выпустить stream_select, чтобы проверить, есть ли какие-либо данные для получения. Обработайте и отправьте данные назад.
Ответ 3
Термин "асинхронный" часто используется в сетевом программировании. Для ввода/вывода асинхронный часто используется как другое слово для неблокирования. Это означает, что процесс может продолжаться до того, как вызов в сети api завершил передачу.
Для выполнения процесса в целом асинхронный означает, что несколько команд могут быть вычислены сразу (одновременно).
Другими словами, асинхронный ввод-вывод не является по-настоящему асинхронным, если несколько потоков не используются, чтобы одновременно допускать множественные чтения/записи/принятия - все сокеты должны подождать синхронного неблокирующего вызова, если у него есть данные для чтения/записи или в противном случае не блокировать, а чтение/запись большого файла может занять секунды или даже минуты, если не прерваться. Обратите внимание, что для этого потребуется идеальный поток между клиентом и сервером, а сам TCP прервет передачу. Например, загрузка сервера быстрее, чем клиент может загрузить, приведет к блокировке записи.
Итак, со строгой точки зрения PHP не способен выполнять асинхронную сеть, только не блокируя. Короче говоря, прогрессирование процесса прекратится, когда сетевой вызов сможет с пользой читать/писать и т.д. Однако процесс будет продолжаться, когда вызов не сможет с пользой читать/писать или в противном случае блокируется. В действительно асинхронной системе процесс будет продолжаться независимо, а чтение/запись будет выполняться в другом потоке. Обратите внимание, что блокировка ввода-вывода все равно может выполняться асинхронно, если выполняется в другом потоке.
Кроме того, PHP не может выполнять операции ввода-вывода с событиями без установки расширения, которое его поддерживает. В противном случае вам нужно будет сделать какую-либо форму опроса, чтобы делать неблокирующие операции ввода-вывода в PHP. Код из Chaos был бы функциональным неблокирующим примером чтения, если он использовал socket_select.
С учетом сказанного функция выбора по-прежнему будет допускать истинное неблокирующее поведение в PHP. В C службы опроса имеют потерю производительности по сравнению с управляемым событием, поэтому я уверен, что он будет таким же для PHP. Но эта потеря находится в наносекундах-микросекундах в зависимости от количества сокетов, где время, сохраненное от неблокирующего вызова, обычно составляет миллисекунды или даже секунды, если вызов сделан для ожидания.
Ответ 4
AFAIK PHP строго односторонне, что означает, что вы не можете делать это асинхронно, потому что выполнение Script всегда линейно.
Прошло некоторое время с тех пор, как я это сделал, но, насколько я помню, вы можете только открыть сокет и продолжить выполнение Script при получении данных.