- Examples
- TCP/IP Connection
- User Contributed Notes 3 notes
- # Sockets
- # Sending data to the server
- # Receiving data from the server
- # Closing the socket
- # TCP server socket
- # Socket creation
- # Socket binding
- # Set a socket to listening
- # Handling connection
- # Closing the server
- # UDP server socket
- # Creating a UDP server socket
- # Binding a socket to an address
- # Sending a packet
- # Receiving a packet
- # Closing the server
- # Handling socket errors
Examples
This example shows a simple talkback server. Change the address and port variables to suit your setup and execute. You may then connect to the server with a command similar to: telnet 192.168.1.53 10000 (where the address and port match your setup). Anything you type will then be output on the server side, and echoed back to you. To disconnect, enter ‘quit’.
#!/usr/local/bin/php -q
error_reporting ( E_ALL );
/* Allow the script to hang around waiting for connections. */
set_time_limit ( 0 );
/* Turn on implicit output flushing so we see what we’re getting
* as it comes in. */
ob_implicit_flush ();
$address = ‘192.168.1.53’ ;
$port = 10000 ;
if (( $sock = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP )) === false ) echo «socket_create() failed: reason: » . socket_strerror ( socket_last_error ()) . «\n» ;
>
if ( socket_bind ( $sock , $address , $port ) === false ) echo «socket_bind() failed: reason: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
>
if ( socket_listen ( $sock , 5 ) === false ) echo «socket_listen() failed: reason: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
>
do if (( $msgsock = socket_accept ( $sock )) === false ) echo «socket_accept() failed: reason: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
break;
>
/* Send instructions. */
$msg = «\nWelcome to the PHP Test Server. \n» .
«To quit, type ‘quit’. To shut down the server type ‘shutdown’.\n» ;
socket_write ( $msgsock , $msg , strlen ( $msg ));
do if ( false === ( $buf = socket_read ( $msgsock , 2048 , PHP_NORMAL_READ ))) echo «socket_read() failed: reason: » . socket_strerror ( socket_last_error ( $msgsock )) . «\n» ;
break 2 ;
>
if (! $buf = trim ( $buf )) continue;
>
if ( $buf == ‘quit’ ) break;
>
if ( $buf == ‘shutdown’ ) socket_close ( $msgsock );
break 2 ;
>
$talkback = «PHP: You said ‘ $buf ‘.\n» ;
socket_write ( $msgsock , $talkback , strlen ( $talkback ));
echo » $buf \n» ;
> while ( true );
socket_close ( $msgsock );
> while ( true );
Example #2 Socket example: Simple TCP/IP client
This example shows a simple, one-shot HTTP client. It simply connects to a page, submits a HEAD request, echoes the reply, and exits.
echo «
TCP/IP Connection
\n» ;
/* Get the port for the WWW service. */
$service_port = getservbyname ( ‘www’ , ‘tcp’ );
/* Get the IP address for the target host. */
$address = gethostbyname ( ‘www.example.com’ );
/* Create a TCP/IP socket. */
$socket = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP );
if ( $socket === false ) echo «socket_create() failed: reason: » . socket_strerror ( socket_last_error ()) . «\n» ;
> else echo «OK.\n» ;
>
echo «Attempting to connect to ‘ $address ‘ on port ‘ $service_port ‘. » ;
$result = socket_connect ( $socket , $address , $service_port );
if ( $result === false ) echo «socket_connect() failed.\nReason: ( $result ) » . socket_strerror ( socket_last_error ( $socket )) . «\n» ;
> else echo «OK.\n» ;
>
$in = «HEAD / HTTP/1.1\r\n» ;
$in .= «Host: www.example.com\r\n» ;
$in .= «Connection: Close\r\n\r\n» ;
$out = » ;
echo «Sending HTTP HEAD request. » ;
socket_write ( $socket , $in , strlen ( $in ));
echo «OK.\n» ;
echo «Reading response:\n\n» ;
while ( $out = socket_read ( $socket , 2048 )) echo $out ;
>
echo «Closing socket. » ;
socket_close ( $socket );
echo «OK.\n\n» ;
?>
User Contributed Notes 3 notes
You can easily extend the first example to handle any number of connections instead of jsut one
#!/usr/bin/env php
error_reporting ( E_ALL );
/* Permitir al script esperar para conexiones. */
set_time_limit ( 0 );
/* Activar el volcado de salida implícito, así veremos lo que estamo obteniendo
* mientras llega. */
ob_implicit_flush ();
$address = ‘127.0.0.1’ ;
$port = 10000 ;
if (( $sock = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP )) === false ) echo «socket_create() falló: razón: » . socket_strerror ( socket_last_error ()) . «\n» ;
>
if ( socket_bind ( $sock , $address , $port ) === false ) echo «socket_bind() falló: razón: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
>
if ( socket_listen ( $sock , 5 ) === false ) echo «socket_listen() falló: razón: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
>
//clients array
$clients = array();
do $read = array();
$read [] = $sock ;
$read = array_merge ( $read , $clients );
// Set up a blocking call to socket_select
if( socket_select ( $read , $write = NULL , $except = NULL , $tv_sec = 5 ) < 1 )
// SocketServer::debug(«Problem blocking socket_select?»);
continue;
>
// Handle new Connections
if ( in_array ( $sock , $read ))
if (( $msgsock = socket_accept ( $sock )) === false ) echo «socket_accept() falló: razón: » . socket_strerror ( socket_last_error ( $sock )) . «\n» ;
break;
>
$clients [] = $msgsock ;
$key = array_keys ( $clients , $msgsock );
/* Enviar instrucciones. */
$msg = «\nBienvenido al Servidor De Prueba de PHP. \n» .
«Usted es el cliente numero: < $key [ 0 ]>\n» .
«Para salir, escriba ‘quit’. Para cerrar el servidor escriba ‘shutdown’.\n» ;
socket_write ( $msgsock , $msg , strlen ( $msg ));
// Handle Input
foreach ( $clients as $key => $client ) < // for each client
if ( in_array ( $client , $read )) if ( false === ( $buf = socket_read ( $client , 2048 , PHP_NORMAL_READ ))) echo «socket_read() falló: razón: » . socket_strerror ( socket_last_error ( $client )) . «\n» ;
break 2 ;
>
if (! $buf = trim ( $buf )) continue;
>
if ( $buf == ‘quit’ ) unset( $clients [ $key ]);
socket_close ( $client );
break;
>
if ( $buf == ‘shutdown’ ) socket_close ( $client );
break 2 ;
>
$talkback = «Cliente < $key >: Usted dijo ‘ $buf ‘.\n» ;
socket_write ( $client , $talkback , strlen ( $talkback ));
echo » $buf \n» ;
>
# Sockets
The second line fails gracefully if connection failed.
socket_connect($socket, "chat.stackoverflow.com", 6667) or onSocketFailure("Failed to connect to chat.stackoverflow.com:6667", $socket);
# Sending data to the server
The socket_write function sends bytes through a socket. In PHP, a byte array is represented by a string, which is normally encoding-insensitive.
socket_write($socket, "NICK Alice\r\nUSER alice 0 * :Alice\r\n");
# Receiving data from the server
The following snippet receives some data from the server using the socket_read function.
Passing PHP_NORMAL_READ as the third parameter reads until a \r / \n byte, and this byte is included in the return value.
Passing PHP_BINARY_READ , on the contrary, reads the required amount of data from the stream.
If socket_set_nonblock was called in prior, and PHP_BINARY_READ is used, socket_read will return false immediately. Otherwise, the method blocks until enough data (to reach the length in the second parameter, or to reach a line ending) are received, or the socket is closed.
This example reads data from a supposedly IRC server.
while(true) // read a line from the socket $line = socket_read($socket, 1024, PHP_NORMAL_READ); if(substr($line, -1) === "\r") // read/skip one byte from the socket // we assume that the next byte in the stream must be a \n. // this is actually bad in practice; the script is vulnerable to unexpected values socket_read($socket, 1, PHP_BINARY_READ); > $message = parseLine($line); if($message->type === "QUIT") break; >
# Closing the socket
Closing the socket frees the socket and its associated resources.
# TCP server socket
# Socket creation
Create a socket that uses the TCP. It is the same as creating a client socket.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
# Socket binding
Bind connections from a given network (parameter 2) for a specific port (parameter 3) to the socket.
The second parameter is usually «0.0.0.0» , which accepts connection from all networks. It can also
One common cause of errors from socket_bind is that the address specified is already bound to another process
(opens new window) . Other processes are usually killed (usually manually to prevent accidentally killing critical processes) so that the sockets would be freed.
socket_bind($socket, "0.0.0.0", 6667) or onSocketFailure("Failed to bind to 0.0.0.0:6667");
# Set a socket to listening
Make the socket listen to incoming connections using socket_listen . The second parameter is the maximum number of connections to allow queuing before they are accepted.
# Handling connection
A TCP server is actually a server that handles child connections. socket_accept creates a new child connection.
$conn = socket_accept($socket);
Data transferring for a connection from socket_accept is the same as that for a TCP client socket
When this connection should be closed, call socket_close($conn); directly. This will not affect the original TCP server socket.
# Closing the server
On the other hand, socket_close($socket); should be called when the server is no longer used. This will free the TCP address as well, allowing other processes to bind to the address.
# UDP server socket
A UDP (user datagram protocol) server, unlike TCP, is not stream-based. It is packet-based, i.e. a client sends data in units called «packets» to the server, and the client identifies clients by their address. There is no builtin function that relates different packets sent from the same client (unlike TCP, where data from the same client are handled by a specific resource created by socket_accept ). It can be thought as a new TCP connection is accepted and closed every time a UDP packet arrives.
# Creating a UDP server socket
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
# Binding a socket to an address
The parameters are same as that for a TCP server.
socket_bind($socket, "0.0.0.0", 9000) or onSocketFailure("Failed to bind to 0.0.0.0:9000", $socket);
# Sending a packet
This line sends $data in a UDP packet to $address : $port .
socket_sendto($socket, $data, strlen($data), 0, $address, $port);
# Receiving a packet
The following snippet attempts to manage UDP packets in a client-indexed manner.
$clients = []; while (true) socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true or onSocketFailure("Failed to receive packet", $socket); $address = "$ip:$port"; if (!isset($clients[$address])) $clients[$address] = new Client(); $clients[$address]->handlePacket($buffer); >
# Closing the server
socket_close can be used on the UDP server socket resource. This will free the UDP address, allowing other processes to bind to this address.
# Handling socket errors
socket_last_error can be used to get the error ID of the last error from the sockets extension.
socket_strerror can be used to convert the ID to human-readable strings.
function onSocketFailure(string $message, $socket = null) if(is_resource($socket)) $message .= ": " . socket_strerror(socket_last_error($socket)); > die($message); >