我的PHP套接字库有一个奇怪的问题:我似乎无法检测/区分服务器EOF,因此我的代码无助地进入无限循环。
下面进一步说明;首先,一些背景(这里没有什么特别的花哨):
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '127.0.0.1', 8081);
for (;;) {
$read = [$socket];
$except = NULL;
$write = [];
print "Select <";
$n = socket_select($read, $write, $except, NULL);
print ">\n";
if (count($read)) {
print "New data: ";
#socket_recv($socket, $data, 1024, NULL);
$data = socket_read($socket, 1024);
print $data."\n";
}
print "Socket status: ".socket_strerror(socket_last_error())."\n";
}
上面的代码只是连接到服务器并打印它读取的内容。它是我正在编写的小型套接字库中的缩减版本。
为了进行测试,我目前正在使用ncat -vvklp 8081
绑定套接字并成为服务器。随着运行,我可以启动上面的代码,它连接和工作 - 例如,我可以键入ncat
窗口,PHP接收它。 (从PHP发送数据也有效,但我已将该代码排除在外,因为它不相关。)
然而,在我^C
ncat
的那一刻,上面的代码进入了一个硬无限循环 - 而且PHP说套接字上没有错误。
我正在试图弄清楚按钮在哪里弄脏了PHP并让它意识到对等已断开连接。
socket_get_status()
是一个很大的用词 - 它是stream_get_meta_data()
的别名,它实际上不适用于套接字!
feof()
同样会提出Warning: feof(): supplied resource is not a valid stream resource
。
我找不到用于检测对等EOF的socket_*
函数。
One of the PHP manual notes for socket_read()
最初阻止我使用该功能,所以我使用socket_recv()
代替,但我最终尝试了以防万一 - 但没有骰子;切换接收呼叫无效。
我已经发现,观看套接字进行写入然后尝试写入它会突然让PHP变为“哦,等等,正确”并开始返回 Broken pipe
< / em> - 但我对写入服务器不感兴趣,我想从中读取它!
最后,关于评论部分 - 我远更喜欢使用PHP的内置流功能,但stream_*
函数不提供任何处理异步连接事件的方法(我想要的)要做,因为我正在建立多个联系)。我可以stream_socket_client(... STREAM_CLIENT_ASYNC_CONNECT ...)
,但后来无法找到建立连接的时间(6yo PHP bug #52811)。
答案 0 :(得分:1)
好的,我想我也可以将上面的评论转化为答案。所有的功劳都归功于Ryan Vincent,因为我帮助了我的厚重头脑:“
如果对等方已断开连接,socket_recv
将特别返回0
,如果发生任何其他网络错误,则会FALSE
。作为参考,在C中,recv()
的返回值是您刚刚收到的新数据的长度(可以是0
)或{{1指示错误条件(其值可以在-1
中找到)。
使用errno
来表示错误条件(并且只有一种任意类型的错误条件),并不是所有错误方式的PHP标准和唯一。其他网络图书馆也不这样做。
你需要像这样处理它。
0