PHP socket_read () получает только первый байт потока - PullRequest
2 голосов
/ 10 октября 2011

Я получаю очень странное поведение при использовании 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 () не должен ждать заполнения буфера или конца строки?

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

Ответы [ 3 ]

2 голосов
/ 10 октября 2011

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

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

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

1 голос
/ 10 октября 2011

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

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

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

0 голосов
/ 10 октября 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...