socket_accept似乎挂在第一个连接上


socket_accept seems to hang on the first connection

我正在尝试在端口 8195 上制作一个简单的侦听器。当我在 PHP CLI 条件下尝试以下代码块时,它只显示"测试"一次,然后挂起。如果我删除文件"votifier.run",该文件被设计为开/关开关,它仍然继续挂起。它从不显示"客户端已连接"。

此外,如果我尝试在脚本运行时通过端口 8195 上的 Telnet 连接到主机,我只会收到连接失败消息。就像它在寻找一种联系,只是不放弃。

// Set the IP and port to listen to
$address = 'localhost';
$port = 8195;
// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port);
// Start listening for connections
socket_listen($sock);
// Loop continuously
while ( file_exists('votifier.run') ) {
    echo 'Test';
    $client = socket_accept($sock);
    if( $client ) {
            echo 'Client connected';
            // Don't hang on slow connections
            socket_set_timeout($client, 5);
            // Send them our version
            socket_write("VOTIFIER MCWEBLINK'n");
            // Read the 256 byte block
            $block = socket_read($client, 256);
            ...

答案是:socket_accept() 通常会挂起,直到建立连接。如果进行了连接尝试,脚本将继续,但由于套接字是在 localhost 上创建的,因此它只接受来自 localhost 的连接

解决方法是使用外部 IP,而不是"本地主机"或"127.0.0.1"。然后你可以远程登录到它。

我只是在这里猜测,但是您尝试绑定的地址不应该是主机名吗?

如果套接字属于AF_INET系列,则地址是点分四边形表示法的 IP(例如 127.0.0.1)。

编辑

好的,我已经采用了您的脚本并尝试重现您的错误,但无法重现。它有几个缺陷,但没有一个会导致telnet客户端的连接尝试失败。

由于上述都不适用,让我们一一浏览清单:

  • 套接字模块加载/编译
  • 本地主机解析为 127.0.0.1
  • 该端口未被正在运行的任何其他应用程序占用
  • 没有任何防火墙规则会阻止Telnet客户端和服务器之间的通信
  • 允许您连接的计算机连接到服务器主机(如果不是,请尝试使用同一主机)
  • 在 while 循环中检查的文件确实存在
  • 确定脚本中没有其他致命错误会阻止您发布的代码段运行

这些都是我能想到的可能的错误源,atm。 首先尝试修复小缺陷,然后通过清单。

if( $client ) {
    echo 'Client connected';
    // Don't hang on slow connections
    socket_set_option(
        $client,
        SOL_SOCKET,
        SO_RCVTIMEO | SO_SNDTIMEO,
        array('sec' => 5, 'usec' => 0)
    );
    // Send them our version
    socket_write($client, "VOTIFIER MCWEBLINK'n");
                 ^^^^^^^
    // Read the 256 byte block
    $block = socket_read($client, 256);

你应该使用线程。如果客户端从不发送任何内容,您的代码将在 read() 方法中阻塞。每个接受的套接字都应在新线程中完全处理。

您可能需要检查以下内容:PHP Votifier 示例 Minecraft Topsites

它解释了代码的工作原理,它是进行加密、填充 256 个空格并发送数据包的基本功能。你可以使用它,因为你可能想改进它。

您可以在此处查看该插件正在运行的 php 的实时演示:http://topg.org/test_votifier