I have a PHP socket server, well, a chat server if you will, which communicates with an XML flash socket and PHP sockets, and it seems that on one point, one or more random clients get "jammed" (it doesn't matter if it's a flash or PHP socket), that is, they try to write to the server, but the server doesn't get the message. BUT, when the server writes to the jammed socket, it works! So it only jamms in one way.
I've been reading server logs for days, and all I could do was to locate the problem, but not really knowing what the problem is or how to fix it.
So, the server works like this (duuuh):
1 ) the server creates the socket
2 ) while(true) loop starts
3 ) prepare the active clients in the array
4 ) use socket_select() on the active clients
5 ) add new sockets to the array if there are any
6 ) read data from sockets that socket_select returned
7 ) parse data
8 ) repeat loop
At first I thought that there was a problem at point 6. - reading from sockets: at first I tried socket_read() with PHP_NORMAL_READ, than PHP_BINARY_READ, and finnaly I ended up with socket_recv() but the problem still presists. That gave me the answer to the question "where does it start?"
And as it turns out the socket_select doesn't return the socket, that is trying to write, so no read even occurs because of that.
Now I wonder: WHY doesn't socket_select() return the socket and why does this occur at random - random clients, random duration of the established connection between the client and server.
Here are some main pieces of code I used:
Create the socket (don't worry, all variables are initialized):
Code: Select all
<?php
@$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
@socket_set_option($socket,SOL_SOCKET,SO_REUSEADDR,1);
@socket_bind($socket,$host,$port);
@socket_listen($socket,$max_clients);
@socket_set_nonblock($socket);
?>Code: Select all
<?php
while(TRUE) {
$read[0] = $socket;
for($i=1;$i<count($clients)+1;$i++) {
if($clients[$i] != NULL) {
$read[$i+1] = $clients[$i]['sock'];
}
//debug("got read");
}
$ready = @socket_select($read,$write=NULL,$except=NULL,0);
//debug("ready: $ready");
purgeuserlist();
if(in_array($socket,$read)) {
for($i=1;$i<$max_clients+1;$i++) {
//debug("listening for new connections ($i)");
if(!isset($clients[$i])) {
debug("New client connected");
$res = @socket_accept($socket);
$clients[$i]['sock'] = $res;
@socket_getpeername($clients[$i]['sock'],$ip);
$clients[$i]['ip'] = $ip;
$clients[$i]['id'] = sha1($ip.date("r").rand());
$clients[$i]['name'] = 'user'; //default
$clients[$i]['nick'] = $clients[$i]['name'];
send($i,$policy,true);
dbUsers();
break;
}
elseif($i == $max_clients - 1) {
debug("Too many clients connected!",true);
}
if($ready < 1) {
continue;
//debug("none ready");
}
}
}
if(count($read)>0) {
debug("current reading sockets: ".print_r($read,true));
}
for($i=1;$i<$max_clients+1;$i++) {
$sock = $clients[$i]['sock'];
if(in_array($sock,$read)) {
read($sock,$i);
}
}
//debug("looop");
usleep(10);
if($sleeps++>5000) {
sendall($xml->generate('ping'));
$sleeps=0;
}
//check if kill signal exists
check_shutdown_elapsed();
}?>