socket_listen

(PHP 4 >= 4.1.0, PHP 5)

socket_listen -- Listens for a connection on a socket

Description

bool socket_listen ( resource socket [, int backlog] )

After the socket socket has been created using socket_create() and bound to a name with socket_bind(), it may be told to listen for incoming connections on socket.

A maximum of backlog incoming connections will be queued for processing. If a connection request arrives with the queue full the client may receive an error with an indication of ECONNREFUSED, or, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.

注: The maximum number passed to the backlog parameter highly depends on the underlying platform. On Linux, it is silently truncated to SOMAXCONN. On win32, if passed SOMAXCONN, the underlying service provider responsible for the socket will set the backlog to a maximum reasonable value. There is no standard provision to find out the actual backlog value on this platform.

socket_listen() is applicable only to sockets of type SOCK_STREAM or SOCK_SEQPACKET.

如果成功则返回 TRUE,失败则返回 FALSE。 The error code can be retrieved with socket_last_error(). This code may be passed to socket_strerror() to get a textual explanation of the error.

See also socket_accept(), socket_bind(), socket_connect(), socket_create() and socket_strerror().


add a note add a note User Contributed Notes
01-Dec-2005 11:17
// How to set up a UDP polling service using a system trigger
// avoiding intensive pooling loop

  // set up a socket
  $sux = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
  if (!$sux) exit('create error');

  // designate a port on the socket to recieve data
  if (!socket_bind($sux, $local_ip, 2210)) exit('bind error');

  $suxref[] =& $sux; // create a reference to the socket as an array
  $ip = '';
  $port = 0;
  do {

     // let the system take care of polling for UDP data
     socket_select($suxref, $write = NULL, $except = NULL, 5);  // sec. timout

     // get the UDPdata with the sender's IP/port
     $z = @socket_recvfrom($sux, $buf, 9999, 0, $ip, $port);
    
     // return some data to the sender IP/port 
     if (strlen($buf) > 0) {
       echo "\r\nRemote sent: " . $buf;
       socket_sendto($sux,  "I hear you", 9999, 0x4, $ip, $port);
       }
     }
  while(true);
Tarik Kettani
01-Oct-2005 02:54
For a UDP listening server in php, let's say you need something to listen for 2 seconds and give you all the received data in that time .. beware of the cpu load of a while(true) or while (time() <= $timeout) kinda thing ...

i managed to go from a 100% cpu usage to something more reasonable by introducing a little microsleep between the socket_recv polls :

$sock2 = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if(!socket_bind($sock2, $your_ip, 666))
{
   socket_close($sock2);
   die( 'socket_bind failed: '.socket_strerror(socket_last_error()));
}

socket_set_nonblock($sock2);

$timeout = time() + (2); // 3 seconds timeout

while (time() <= $timeout)
{
   while (@socket_recv($sock2, $data, 8192, 0))
   {
   // do something useful with $data :)
   }
   usleep(100000); // 100ms delay keeps the doctor away
}   
socket_close($sock2);

bonne chance :)
lewislp at yahoo dot com
31-Aug-2005 03:13
socket_listen() cannot be used for UDP communications as discussed below.

In addition, the example below discusses UDP connections, which only exist if the application manages them through a state table (the OS does not create a UDP connection upon receiving a datagram).  Having a function named socket_connect() that determines the remote IP and port only confuses the matter by giving the indication of some sort of connection handshake between two hosts.  Rather, socket_connect() only specifies the remote IP and port used by subsequent socket_send() calls.  You can achieve the same effect by skipping socket_connect() altogether and specifying the remote IP and port in socket_sendto() calls.

If you find yourself writing a connection-based protocol on top of UDP, consider using TCP.  If your application requires streaming data of some sort, use TCP to manage connections and control messages, and UDP to handle the streaming data (H.323 is an example of a suite of TCP and UDP protocols working in conjunction).
john at bhdnet dot com
24-Feb-2005 04:14
One suggestion for the above example for working with UDP.

The example uses the same socket to connect to a machine thus closing the listening socket and forcing the re-creation of a new UDP socket and wasting alot of processor time.

Instead it would be better to follow the standard TCP/IP operation method whereby you have one socket listening and create new sockets to form active connections.

So when the UDP socket is incoming create a new socket identical (bind to a different port number) and then connect.

Of course, if you wanted bi-directional communication you should always use TCP/IP because it is more reliable and has methods of packet arrangement and recovery.
tsuna at tsunaquake d0t c0m
20-Feb-2005 09:11
As you can see, socket_listen() doesn't work with UDP sockets. I found it difficult to make a daemon listenning for incoming connections in UDP (especially if this daemon has to reply to the UDP client), so here is how I made it:

<?php
// example of "daemon" in UDP
while(TRUE) { // never stop the daemon
  
$socketD = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // create an UDP socket

  
echo 'Creating socket... '; // YES, the socket is creating EACH TIME the while loops
  
  
if($socketD === FALSE) { //omg, something went wrong
      
echo 'socket_create failed: '.socket_strerror(socket_last_error())."\n";
       exit(
1);
   }
  
   echo
"OK\nBinding the socket on 0.0.0.0:27123 ... ";
  
// let the daemon listen on the port 27123 on all interfaces
  
if(!socket_bind($socketD, "0.0.0.0", 27123)) {
      
socket_close($socketD);
       echo
'socket_bind failed: '.socket_strerror(socket_last_error())."\n";
       exit(
1);
   }
  
   echo
"OK\nNow ready to accept connections.\nListening on the socket ... \n";
  
// so far, our socket is open and bound to a port: it's listening for ONE incoming connection

   // this is a special way of socket_read()'ing what's on the socket once someone establishes a connection
  
socket_recvfrom($socketD, $buf, 65535, 0, $clientIP, $clientPort);
   if(
$buf === FALSE) { // something went wrong
      
echo 'socket_read() returned false : '.socket_strerror(socket_last_error())."\n";
       continue;
   } elseif(
strlen($buf) === 0) { // this should mean "client closed the connection"
      
echo 'socket_read() returned an empty string : '.socket_strerror(socket_last_error())."\n";
       continue;
   }

   echo
'Incoming connection from '.$clientIP.':'.$clientPort.' ... ';

  
// ok now thats the tricky part
   // if you want to reply to the client on the UDP socket it opened, you need to connect your listening socket on them
   // this won't work unless the client puts their IP in the IP  header of the packets it's sending to your socket
   // UDP sessions don't require them to do so, and if they don't, you have no way to tell who's talking to you on the socket, and therefore no way to reply
   // so if you want to interact with the client, you have to connect your socket on them, but by doing so, you're no longer listening to other incoming connections
   // one way to fixe that would be to fork the script when an incoming connection arrives and then stop the forked script once the client exits
  
if(!socket_connect($socketD, $clientIP, $clientPort)) {
       echo
'socket_create failed to connect the clientsock on '.$clientIP.':'.$clientPort.' : '.socket_strerror(socket_last_error())."\n";
      
socket_close($socketD);
       continue;
   }
   echo
'connected'."\n"; // cool, now we can reply to the client

   // now you can interact with the client using socket_write() and socket_read()

   // once you're finished, you need to socket_close() your sockets and let the while loop and re-create the listenning socket (because you're no longer listenning for new incoming connections)
} // end of the infinite while
?>

Other documentation pages will provide you with handy links & examples of scripts forking themselves so that you can adapt this script to make it a real daemon working in UDP

I hope this will be helpfull
- Tsuna.