Не могу прочитать из сокета (зависает) - PullRequest
7 голосов
/ 09 ноября 2010

Редактировать: Извините, случайно опубликован с заголовком для другого вопроса. Исправлено.

Привет, ребята,

Я использую PHP для подключения к локальному серверу сокетов C ++, чтобы поддерживать состояние между веб-приложением и парой демонов. Я могу отправлять данные на сервер сокетов, но не получать от него; он просто блокируется на socket_read() и зависает бесконечно. Я забыл что-то глупое (например, символ NULL или другую комбинацию символов новой строки)? PHP ниже:

socket_connect($sock, $addr, $port); 
socket_write($sock, 'Hello world');
$str = '';
while($resp = socket_read($sock, 1000))
    $str .= $resp;
socket_close($sock);
die("Server said: {$str}");

Ниже показана соответствующая часть сервера сокетов (обратите внимание, что операторы << и >> перегружены):

std::string data;
sock >> data;
sock << data << std::endl;

Где >> звонит Socket::recv(std::string&) и >> звонит Socket::send(const std::string&).

Это нормально работает с (например) telnet, но PHP не хочет играть хорошо. Любые мысли / предложения приветствуются.

Ответы [ 4 ]

9 голосов
/ 09 ноября 2010

Сокеты в PHP, как и в большинстве языков программирования, по умолчанию открываются в режиме блокировки, если не указано иное с помощью socket_set_nonblock.

Это означает, что, если не происходит тайм-аут / ошибка или не получены данные, socket_read будет висеть там вечно.

Поскольку ваш символ завершения выглядит новой строкой, попробуйте:

while($resp = socket_read($sock, 1000)) {
   $str .= $resp;
   if (strpos($str, "\n") !== false) break;
}
socket_close($sock);
die("Server said: $str");
1 голос
/ 09 ноября 2010

TCP-сокеты обычно пытаются объединить несколько небольших вызовов отправки в один пакет, чтобы избежать отправки слишком большого количества пакетов ( алгоритм Нейгла ). Это может быть причиной того, что вы ничего не можете получить после вызова send (). Вам придется открыть сокет с помощью TCP_NODELAY , чтобы избежать этого.

0 голосов
/ 16 ноября 2013

Вы также можете попробовать это при чтении из сокета:

if(socket_recv ( $socket , $response , 2048 , MSG_PEEK)!==false)
{
   echo "Server said: $response";
}

Примечание. Использование MSG_WAITALL вместо MSG_PEEK может привести к зависанию сокета (из одного опыта, который я когда-то имел).

0 голосов
/ 09 ноября 2010

Я на самом деле только что исправил проблему, похожую на эту, за исключением каналов ( Является ли php fopen несовместимым с POSIX, открытым для каналов ). Я не знаю, в какой степени решение будет похоже, но, возможно, стоит посмотреть? Я согласен с RageD в том, что вы должны вставить cout между строками чтения и записи, чтобы проверить и убедиться, что C ++ висит на строке данных sock >> или на сокете << line data ... </p>

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