Harry Beasant
Harry Beasant

Reputation: 1014

Socket taking too long to close

I have sockets querying a game server on a few pages in my application. I have an issue that when i navigate too quickly between the pages, the socket has no closed properly and the error i get is this;

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

I have to wait around 4-5 seconds after each page has fully loaded, for it to close.

Here is the code for the socket;

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 );                  
}   

And here is the code for the socket on the other page;

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
    );
}

Thanks!

Upvotes: 3

Views: 1135

Answers (1)

Wug
Wug

Reputation: 13196

Woohoo, specific knowledge I know a lot about! There should be a minecraft tag.

I believe this is actually a minecraft server limitation, as opposed to a problem with your php code. You may notice that if you are using the minecraft client and you visit the multiplayer page several times quickly, you will experience the same issue (connections to servers to query player count and MOTD will be denied). It resolves itself if you wait 5 or 6 seconds between visits.

Your solution might therefore be to cache the response from servers for 10 seconds or 30 seconds or so, so that the server doesn't deny them.

I don't know if you have a local SQL database you can use, but you should be able to set yourself up a table containing the server ip (not the hostname, which is not guaranteed to be unique. The IP isn't either but its a better bet), the MOTD, the current and max players, and a last-checked timestamp. You can simply do your database query, check the timestamp to make sure the cached value hasnt expired, and if it has, query the server directly and store the result in the database.

Upvotes: 3

Related Questions