【问题标题】:Socket taking too long to close套接字关闭时间过长
【发布时间】:2012-09-07 21:46:13
【问题描述】:

我在我的应用程序的几个页面上有查询游戏服务器的套接字。我有一个问题,当我在页面之间导航太快时,套接字没有正确关闭,我得到的错误是这样的;

socket_recv() [function.socket-recv]: unable to read from socket [104]: Connection reset by peer

我必须在每个页面完全加载后等待大约 4-5 秒才能关闭。

这是套接字的代码;

function QueryMinecraft( $IP, $Port, $Timeout =1 )
{
    $Socket = Socket_Create( AF_INET, SOCK_STREAM, SOL_TCP );

    Socket_Set_Option( $Socket, SOL_SOCKET, SO_SNDTIMEO, array( 'sec' => (int)$Timeout, 'usec' => 0 ) );

    if( $Socket === FALSE || @Socket_Connect( $Socket, $IP, (int)$Port ) === FALSE )
    {
        Socket_Close( $Socket );
        return FALSE;
    } else {
        Socket_Close( $Socket );
        return TRUE;
    }      
    Socket_Close( $Socket );                  
}   

这是另一页上的套接字代码;

function QueryMinecraft( $IP, $Port, $Timeout = 3 )
{
    $Socket = Socket_Create( AF_INET, SOCK_STREAM, SOL_TCP );

    Socket_Set_Option( $Socket, SOL_SOCKET, SO_SNDTIMEO, array( 'sec' => (int)$Timeout, 'usec' => 0 ) );

    if( $Socket === FALSE || @Socket_Connect( $Socket, $IP, (int)$Port ) === FALSE )
    {
        return FALSE;
    }

    Socket_Send( $Socket, "\xFE", 1, 0 );
    $Len = Socket_Recv( $Socket, $Data,256, 0 );


    if( $Len < 4 || $Data[ 0 ] != "\xFF" )
    {
        return FALSE;
    }

    $Data = SubStr( $Data, 3 );
    $Data = iconv( 'UTF-16BE', 'UTF-8', $Data );
    $Data = Explode( "\xA7", $Data );

    return Array(
        'HostName'   => SubStr( $Data[ 0 ], 0, -1 ),
        'Players'    => isset( $Data[ 1 ] ) ? IntVal( $Data[ 1 ] ) : 0,
        'MaxPlayers' => isset( $Data[ 2 ] ) ? IntVal( $Data[ 2 ] ) : 0
    );
}

谢谢!

【问题讨论】:

    标签: php sockets minecraft


    【解决方案1】:

    哇哦,我知道很多具体知识!应该有一个 minecraft 标签。

    我相信这实际上是我的世界服务器限制,而不是您的 php 代码的问题。您可能会注意到,如果您正在使用 minecraft 客户端并且您多次快速访问多人游戏页面,您将遇到相同的问题(连接到服务器以查询玩家人数和 MOTD 将被拒绝)。如果您在两次访问之间等待 5 或 6 秒,它会自行解决。

    因此,您的解决方案可能是将来自服务器的响应缓存 10 秒或 30 秒左右,以便服务器不会拒绝它们。

    我不知道你有没有本地的SQL数据库可以使用,但是你应该可以自己设置一个包含服务器ip的表(不是主机名,不保证是唯一的。IP是也不是,但它是一个更好的选择)、MOTD、当前和最大玩家以及最后检查的时间戳。您可以简单地进行数据库查询,检查时间戳以确保缓存值未过期,如果已过期,则直接查询服务器并将结果存储在数据库中。

    【讨论】:

    • 我已经很久没有研究服务器代码了,但是从这种行为的普遍性来看,它是服务器的行为。
    • 好吧,这真的很烦人,可能不得不让页面加载速度变慢哈哈:L
    • 感谢您的回复,我可能会暂停页面加载 3 秒。
    • 查看缓存建议。它有优点。此外,一个简单的页面加载延迟仅在只有一个人查看该页面时才能解决问题,如果多次尝试,它仍然会中断(除非您错开他们的请求,因此每 3 秒最多发生一个页面加载,这是可怕的想法)。如果您绝对必须实时跟踪玩家,您可以为服务器编写一个插件,该插件将打开一个到您的数据库后端的套接字并为 MOTD 和玩家提供实时更新,但这将是很多工作。
    • 你好,我会试试的,我怎么去缓存它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2011-01-12
    • 2020-01-25
    • 2016-11-10
    • 1970-01-01
    • 2017-11-07
    • 2011-01-22
    相关资源
    最近更新 更多