使用PHP套接字模块

时间:2016-09-09 11:32:06

标签: php sockets eof

我的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)。

1 个答案:

答案 0 :(得分:1)

好的,我想我也可以将上面的评论转化为答案。所有的功劳都归功于Ryan Vincent,因为我帮助了我的厚重头脑:“

如果对等方已断开连接,

socket_recv将特别返回0,如果发生任何其他网络错误,则会FALSE

作为参考,在C中,recv()的返回值是您刚刚收到的新数据的长度(可以是0)或{{1指示错误条件(其值可以在-1中找到)。

使用errno来表示错误条件(并且只有一种任意类型的错误条件),并不是所有错误方式的PHP标准和唯一。其他网络图书馆也不这样做。

你需要像这样处理它。

0