PHP socket_read () получает только первый байт потока

Я получаю очень странное поведение при использовании socket_read () в linux.

Я использую socket_read с ограничением буфера 2048.

В то время как на моей системе Windows это получает весь ответ, на моем Linux-сервере он просто получает первый байт ответа.

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); if (!socket_connect($sock, 'my-server.dyndns.org', 8888)) { die('no connect'); } $req = 'request'; socket_write($sock, $req); if (false !== ($buf = socket_read($sock, 2048)) { echo $buf; // This only contains the first byte of the response. } socket_close($sock); 

Если я снова вызову socket_read (), он получит оставшуюся часть строки:

 // This works: while((false !== ($buf = socket_read($sock, 2048)))) { echo "Read ".strlen($buf)." bytes from socket_read().\n"; if ($buf == "") break; $b .= $buf; sleep(1); } /* Output: * * Read 1 bytes from socket_read(). * Read 307 bytes from socket_read(). * Read 0 bytes from socket_read(). * Done. */ 

Если я жду 2 секунды перед вызовом socket_read (), я также получаю действительный ответ:

 // This also works: sleep(2); if (false !== ($buf = socket_read($sock, 2048)) { echo $buf; // all 308 bytes are read correctly. } 

Должна ли socket_read () ждать завершения заполнения буфера или окончания строки?

Что я делаю не так?

Вам нужно количественно определить «весь ответ».

Если «весь ответ» означает, что все данные, которые записываются в сокет до его закрытия, тогда вам нужно использовать цикл, получающий больше данных. recv не гарантирует отправку всех данных в один кусок.

Я настоятельно рекомендую вам не использовать древние функции socket_, но вместо этого вместо fsockopen и fread.

Известно, что сетевой стек на Linux лучше (быстрее), чем на окнах (это субъективно, скажем так: он ведет себя по-другому). С другой стороны, это означает, что ваш код также должен иметь дело с различиями.

Сокеты не в режиме реального времени, а асинхронные. Поэтому, если вы пишете что-то в сокет, вы не можете ожидать, что вы уже можете прочитать на нем. Вы должны дать удаленному демона некоторое время, чтобы на самом деле ответить на вашу запись.

Только если удаленная сторона действительно что-то написала в вашем сокете, и сеть передала эти данные, вы можете ее прочитать.

В руководстве по php говорится, что чтение заканчивается с помощью \ r \ n, если для типа установлено значение PHP_NORMAL_READ string socket_read (resource $ socket, int $ length [, int $ type = PHP_BINARY_READ])

Возможно, в вашем случае должно быть socket_read ($ sock, 2048, PHP_NORMAL_READ), чтобы указать, что он должен прекратить чтение с \ r \ n

В противном случае вы можете попробовать с обычным fsockopen и fread вместо этого … обычно это нормально работает на linux.