Marcus Krueger
Marcus Krueger

Reputation: 163

PHP Socket Server Hangs

I've worked hours and hours on this, and I can't figure it out. I've browsed the posts on here trying to find the solution also and to no avail.

I have a Socket Server setup for my browser-based game. I've stripped it down trying to find the issue, and it seems that fread is hanging because if I comment out "fread($fp, 10024);" then it runs fine, but of course doesn't read the response.

While I debug this, I've broken the files down to the basics.

I have the Socket Server: 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);

Then I have Test.php which should open the socket and read a response.

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

$errstr doesn't display an error, because when I start ChatServer.php then reload Test.php, it never reloads. It hangs for minutes and lags my entire server. I'm running on a VPS. This worked fine before, then suddenly stopped working, and I can't figure out why.

Edit: Thanks to GigaWatt, I was able to get it working. Here is the code I used if you have the same issue. :)

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

Just use stream_get_meta_data and then unread_bytes.

Upvotes: 2

Views: 1605

Answers (2)

Mr. Llama
Mr. Llama

Reputation: 20889

The call to socket_read is a blocking call, meaning everything stops until the specified number of bytes have been read.

If you need to continue processing, consider using stream_get_meta_data (the unread_bytes value) to check how much unread data is waiting.
Once it reaches the desired threshold, then call socket_read.

https://www.php.net/manual/en/function.stream-get-meta-data.php

Upvotes: 2

a sad dude
a sad dude

Reputation: 2825

It does exactly what you tell it to: waits for 12048 / 10024 bytes of data or socket being closed.

You might be interested in using a non-blocking socket (socket_set_nonblock/stream_set_blocking) and a socket_select loop or libevent.

Upvotes: 1

Related Questions