views:

759

answers:

3

I have a very simple server php code like this

function listenForClients()
 {
      $this->serviceConnection = socket_create(AF_UNIX, SOCK_STREAM, 0);
      socket_bind($this->serviceConnection, "\tmp\mysock", 0);
      socket_listen($this->serviceConnection, 10000000);

      while($clientSocket = socket_accept($this->serviceConnection))
      {
           $clientMessage = socket_read($clientSocket, 1024);
           socket_close($clientSocket);
      }
 }


Then I have a very simple client that does this

for ( $counter = 0; $counter <= 1000; $counter ++) {    
   $fp = fsockopen("unix///tmp/mysock", 0, $errno, $errstr);

   if (!$fp){
      echo  "Error: Could not open socket connection at " . $counter . "\n";
      exit;
   }else{    
      fputs ($fp, "hello", strlen("hello"));
      fclose($fp);
   }
}

For some reason, after a random number of connections (around 300-500) fsockopen will return with a warning Resource temporarily unavailable. In the beginning I was getting the warning at around 20-30 connections. But once I increased the backlog parameter in socket_listen it got a bit better to around 300-500. How do I overcome this?

What is the way to build a php server socket to accept a lot of incoming connections per second (sustained).

Thanks!

The full error:

PHP Warning: fsockopen(): unable to connect to unix:///tmp/mysock:0 (Resource temporarily unavailable) in test.php on line 22

+1  A: 

Check your ulimit. Are you overflowing your file descriptor table?

EDIT: the backlog value you have in accept() is bogus. Most OS-es have the max incoming connection queue size on the scale of dozens, not thousands.

Nikolai N Fetissov
It is currently set at "unlimited";
erotsppa
I should've been more clear. Check the open files limit (-n option, or -a for all limits.)
Nikolai N Fetissov
open -n is set at 1024, but does opening the same file socket multiple times uses this limit? Especially after I close each one after I open another one?
erotsppa
Interesting. What platform is this? From the socket pathnames it looks like you are on some mix on Unix and Windows. I was able to reproduce your results on a Mac under regular user, but under root it runs through 1000 connects with no problems. Keep in mind that PHP itself opens some unknown number of files.
Nikolai N Fetissov
Nikolai, thanks for trying it out. What you find is that if your server actually computes anything (say write that string to a file), you will not be able to go through 1000 without that warning. It kind of makes sense, if the server can only have so many backlog connections and its spending time on computation then sooner or later the socket will not accept more connection. Let me know if that is the case and what you think I can do to increase the limit. Thanks!
erotsppa
+1  A: 

I realize this might not be a particularly popular answer, but I wouldn't really recommend PHP as a great language for writing a server that accepts a heavily sustained number of client connections.

TML
Everyone's entitled to their opinion. But I just can't believe that this was the most "useful" answer to this question.
Till
+1  A: 

I've just been looking at this issue (got here through Google) and I've found that a solution to get rid of the error:

PHP Warning: fsockopen(): unable to connect to unix:///tmp/mysock:0 (Resource temporarily unavailable) in test.php on line 22

..is to not use fsockopen() in the writer thread; try something like this instead:

if (! ($cSock = socket_create(AF_UNIX, SOCK_STREAM, 0))) {
    exit("Failed to create socket");
    continue;
} else if (! socket_connect($cSock, IPC_SOCK)) {
    exit("Failed to connect socket");
} else {
    $bw = socket_write($cSock, $msg);
    if ($bw === false) {
        exit("Socket write failed, %s", array(socket_strerror(socket_last_error())));
    } else {
        exit("Wrote $bw bytes to socket");
    }
}
socket_shutdown($cSock);
socket_close($cSock);

Better late than never ? ;-)

Robin