【问题标题】:PHP Socket Server HangsPHP 套接字服务器挂起
【发布时间】:2014-05-19 15:28:52
【问题描述】:

我已经为此工作了好几个小时,但我无法弄清楚。我也浏览了这里的帖子,试图找到解决方案,但无济于事。

我为基于浏览器的游戏设置了 Socket 服务器。我已将其剥离以试图找到问题,并且 fread 似乎挂起,因为如果我注释掉“fread($fp, 10024);”然后它运行良好,但当然不会读取响应。

在调试时,我已将文件分解为基本内容。

我有 Socket 服务器:ChatServer.php

set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_get_option($sock, SOL_SOCKET, SO_REUSEADDR);
socket_bind($sock, "127.0.0.1", "9990");
socket_listen($sock, 4);

$chatContent = "Testing, 1, 2, 3.";
do
{
    $childSocket = socket_accept($sock);
    $incomingData = socket_read($childSocket, 12048);

    socket_write($childSocket, $chatContent, strlen($chatContent));
} while(true);

然后我有 Test.php,它应该打开套接字并读取响应。

$fp = fsockopen("127.0.0.1", "9990", $errno, $errstr, 5);
echo $errstr . "<br />";
echo fread($fp, 10024);

$errstr 不会显示错误,因为当我启动 ChatServer.php 然后重新加载 Test.php 时,它永远不会重新加载。它挂了几分钟并且落后于我的整个服务器。我在 VPS 上运行。之前很好用,后来突然停止工作,我不知道为什么。

编辑:感谢 GigaWatt,我能够让它工作。如果您有同样的问题,这是我使用的代码。 :)

    set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_get_option($sock, SOL_SOCKET, SO_REUSEADDR);
socket_bind($sock, "127.0.0.1", "9990");
socket_listen($sock, 4);

$chatContent = "Testing, 1, 2, 3.";
do
{
    $childSocket = socket_accept($sock);
    $meta = stream_get_meta_data($sock);

    if($meta['unread_bytes'] > 0) {
        $incomingData = socket_read($childSocket, $meta['unread_bytes']);
    }

    socket_write($childSocket, $chatContent, strlen($chatContent));
} while(true);

只需使用 stream_get_meta_data,然后使用 unread_bytes。

【问题讨论】:

  • while($incomingData) 替换while(true) 怎么样?
  • 仍然挂起该更改。

标签: php sockets


【解决方案1】:

socket_read 的调用是阻塞调用,这意味着在读取指定的字节数之前一切都会停止。

如果您需要继续处理,请考虑使用stream_get_meta_dataunread_bytes 值)来检查有多少未读数据正在等待。
一旦达到所需的阈值,然后调用socket_read

http://us3.php.net/manual/en/function.stream-get-meta-data.php

【讨论】:

  • 这太棒了!非常感谢!我在这个问题上花了将近 10 个小时,因为我讨厌寻求帮助,并且在几分钟内您就找到了解决方案。
【解决方案2】:

它完全按照您的指示行事:等待 12048 / 10024 字节的数据或关闭套接字。

您可能对使用非阻塞套接字 (socket_set_nonblock/stream_set_blocking) 和 socket_select 循环或 libevent 感兴趣。

【讨论】:

  • 在 PHP 中没有简单的方法可以做到这一点。考虑改用 Node.js,它同样糟糕,但有可爱的非阻塞 API
  • 我听说过很多关于 node.js 的信息。我在一家网络开发公司工作(这是一个个人项目,我是质量保证人员,而不是开发人员),他们将使用 node.js 和其他一些东西来实现自动化。但是,我真的不知道 node.js 是什么。有没有一个非常愚蠢的解释?
  • 它是服务器端的 JavaScript,带有一堆文件系统和套接字 API。如果您了解 JS,只需阅读教程就可以了。您可能想查看似乎适合您的任务的socket.io
猜你喜欢
  • 2014-04-12
  • 2015-09-10
  • 2018-05-07
  • 2018-01-07
  • 2012-07-02
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
相关资源
最近更新 更多