无法读取套接字(挂起)

时间:2010-11-09 19:33:08

标签: php c++ sockets

编辑:抱歉,不小心发布了一个不同问题的标题。固定的。

嘿伙计们,

我正在使用PHP连接到本地C ++套接字服务器,以保持Web应用程序和几个守护进程之间的状态。我可以将数据发送到套接字服务器,但不能从它接收;它只是在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 个答案:

答案 0 :(得分:9)

与大多数编程语言一样,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 :(得分:1)

TCP套接字通常会尝试将多个小型发送呼叫组合到一个数据包中,以避免发送太多数据包(Nagle's algorithm)。这可能是您在send()调用后无法接收任何内容的原因。您必须使用TCP_NODELAY打开套接字以避免这种情况。

答案 2 :(得分:0)

我实际上只修复了与此类似的问题,除了管道(Is php's fopen incompatible with the POSIX open for pipes)。我不知道解决方案在多大程度上是相似的,但也许值得一看?我同意RageD你应该在读写行之间插一个cout来测试并看看C ++是否挂在袜子上&gt;&gt;数据线或袜子&lt;&lt;数据线...

答案 3 :(得分:0)

您还可以在从套接字读取时尝试此操作:

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

注意:使用 MSG_WAITALL 代替 MSG_PEEK 可能会导致套接字挂起(来自我以前的一次体验)。