编辑:抱歉,不小心发布了一个不同问题的标题。固定的。
嘿伙计们,
我正在使用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不想玩得很好。任何想法/建议都表示赞赏。
答案 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 可能会导致套接字挂起(来自我以前的一次体验)。