socket_accept似乎挂在第一个连接上

时间:2012-08-14 08:11:43

标签: php sockets

我正在尝试在端口8195上创建一个简单的侦听器。当我在PHP CLI条件下尝试以下代码块时,它只显示“Test”一次,然后挂起。如果我删除文件'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而不是“localhost”或“127.0.0.1”。然后你可以Telnet到它。

3 个答案:

答案 0 :(得分:2)

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

  

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

修改

好的,我已经拍摄了你的脚本并试图重现你的错误但却没有。它有一些缺陷,但没有一个会导致telnet客户端的连接尝试失败。

由于以上都不适用,我们逐一通过检查表:

  • 加载/编译套接字模块
  • localhost确实解析为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);

答案 1 :(得分:0)

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

答案 2 :(得分:-1)

您可能想要检查一下: PHP Votifier example for Minecraft Topsites

它解释了代码是如何工作的,它是进行加密的基本功能,填满256个空格并发送数据包。您可以稍微使用它,因为您可能希望改进它。

你可以在这里看到插件运行php的现场演示:http://topg.org/test_votifier