Forum Moderators: coopster

Message Too Old, No Replies

PHP socket_read - forced timeout?

socket_read forces near infinite loop locking socket server

         

ethernalite

6:02 pm on Apr 23, 2005 (gmt 0)

10+ Year Member



I hate to barge in here and ask a question as my first post, but I have looked everywhere and simply could not find a practical answer, so I'm hoping someone with expertise in the matter can help me.

The scenario is this: I am trying to write a php socket server to replace a traditional PHP script run by an httpd server. What it does it accept a small request from the client and then do some simple SQL work and return a regular http request.

Normally, I would have just kept the old code and let apache deal with the incoming requests, but the problem is that the simple SQL work (using mySQL) requires an UPDATE query. Even when using an InnoDB that only locks rows, this causes problems for other threads trying to access the same table and creates huge query queues (700+ connections) that cause the mySQL server to choke (and Apache for that matter, managing all the PHP threads).

So, the solution was to simply make a socket server that handles all of the requests in a single threaded environment (since, due to the UPDATE queries, which effectively locked the tables, it was already 'singlethreaded' in a way) I'd worked with php sockets before, so I have a general idea of what I was doing - but never at this scale (the socket server receives around 50 requests/sec). While the script execution time, when it actually receives the request properly, is excellent (<5ms), every few seconds a connection comes along that simply freezes on socket_read() for anywhere between 500 ms to 30 seconds. Obviously, this has something to do with the connection on the other end disconnecting before transmitting all of its data, but socket_read() has no built in timeout function (that I am aware of) to deal with this problem, and at 50 requests a second, a 10 second lockup suddenly means there's 500 connections waiting in queue. Eventually the backlog fills up and begins to reject connections.

Any insight as to how to force a (short) timeout on socket_read()? If this is simply not possible, I will be looking into using fork() to overcome this problem, but I would prefer not, as thread chaos is what inspired me to create this socket server in the first place. :)

Here's the basic code:


if(($socket = socket_create(AF_INET, SOCK_STREAM, 0)) < 0)
die("Socket could not be created!");
if(socket_bind($socket, $address, $port) < 0)
die("Socket could not bind on port $port @ $address!");
if(@socket_listen($socket, 100)< 0)
die("Socket cannot listen on $port!");

while(1)
{$request_headers = "";
if(($request = socket_accept($socket)) > 0)
{
$start = gettimeofday();
socket_getpeername($request, $addr);


while(($buf = socket_read($request, 2048))!== false)
{
$request_headers .= $buf;
if(preg_match("'\r\n\r\n$'s", $request_headers)) // only need to get headers
break;
}


// do stuff here


socket_shutdown($request);
socket_close($request);
}
}

Thanks in advance,
-ethernal

ethernalite

9:27 pm on Apr 23, 2005 (gmt 0)

10+ Year Member



Disregard, problem was solved using socket_set_option, sorry about my stupidity. :)

-ethernal

coopster

2:48 am on Apr 27, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Welcome to WebmasterWorld, ethernalite.

No stupidity and no barging noticed. Unheard of terms in this forum ;)

The only stupid question is the one that doesn't get asked. Glad you got it sorted.