PHP 8.6.0 Beta 1 is available for testing

socket_accept

(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)

socket_acceptAcepta una conexión en un socket

Descripción

function socket_accept(Socket $socket): Socket |false

Una vez que el socket socket ha sido creado con la función socket_create() , vinculado a un nombre con la función socket_bind() , y puesto en espera de conexión con la función socket_listen() , socket_accept() acepta las conexiones en este socket. Una vez que se establece una conexión, se devuelve una nueva instancia de Socket . Esta puede ser utilizada para las comunicaciones. Si hay varias conexiones en espera, se utilizará la primera. Si no hay conexiones en espera, socket_accept() se bloqueará hasta que se presente una conexión. Si socket ha sido configurado como no bloqueante, gracias a socket_set_blocking() o socket_set_nonblock() , se devolverá false .

La instancia de Socket devuelta por socket_accept() no debe ser utilizada para aceptar nuevas conexiones. El socket original socket, que está en espera, permanece abierto y puede ser reutilizado.

Parámetros

socket

Una instancia de Socket creada por socket_create() .

Valores devueltos

Devuelve una nueva instancia de Socket en caso de éxito o false en caso de error. El código de error generado puede ser obtenido llamando a la función socket_last_error() . Este código de error puede ser pasado a la función socket_strerror() para obtener un mensaje de error legible por humanos.

Historial de cambios

Versión Descripción
8.0.0 En caso de éxito, esta función devuelve ahora una instancia de Socket ; anteriormente, se devolvía un resource .

Véase también

Found A Problem?

Learn How To Improve This PageSubmit a Pull RequestReport a Bug
+add a note

User Contributed Notes 5 notes

up
24
lars at opdenkamp dot eu
18 years ago
If you want to make a daemon process that forks on each client connection, you'll find out that there's a bug in PHP. The child processes send SIGCHLD to their parent when they exit but the parent can't handle signals while it's waiting for socket_accept (blocking).
Here is a piece of code that makes a non-blocking forking server.
#!/usr/bin/php -q
<?php
/**
 * Listens for requests and forks on each connection
 */
$__server_listening = true;
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
declare(ticks = 1);
become_daemon();
/* nobody/nogroup, change to your host's uid/gid of the non-priv user */
change_identity(65534, 65534);
/* handle signals */
pcntl_signal(SIGTERM, 'sig_handler');
pcntl_signal(SIGINT, 'sig_handler');
pcntl_signal(SIGCHLD, 'sig_handler');
/* change this to your own host / port */
server_loop("127.0.0.1", 1234);
/**
 * Change the identity to a non-priv user
 */
function change_identity( $uid, $gid )
{
 if( !posix_setgid( $gid ) )
 {
 print "Unable to setgid to " . $gid . "!\n";
 exit;
 }
 if( !posix_setuid( $uid ) )
 {
 print "Unable to setuid to " . $uid . "!\n";
 exit;
 }
}
/**
 * Creates a server socket and listens for incoming client connections
 * @param string $address The address to listen on
 * @param int $port The port to listen on
 */
function server_loop($address, $port)
{
 GLOBAL $__server_listening;
 if(($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0)
 {
 echo "failed to create socket: ".socket_strerror($sock)."\n";
 exit();
 }
 if(($ret = socket_bind($sock, $address, $port)) < 0)
 {
 echo "failed to bind socket: ".socket_strerror($ret)."\n";
 exit();
 }
 if( ( $ret = socket_listen( $sock, 0 ) ) < 0 )
 {
 echo "failed to listen to socket: ".socket_strerror($ret)."\n";
 exit();
 }
 socket_set_nonblock($sock);
 
 echo "waiting for clients to connect\n";
 while ($__server_listening)
 {
 $connection = @socket_accept($sock);
 if ($connection === false)
 {
 usleep(100);
 }elseif ($connection > 0)
 {
 handle_client($sock, $connection);
 }else
 {
 echo "error: ".socket_strerror($connection);
 die;
 }
 }
}
/**
 * Signal handler
 */
function sig_handler($sig)
{
 switch($sig)
 {
 case SIGTERM:
 case SIGINT:
 exit();
 break;
 case SIGCHLD:
 pcntl_waitpid(-1, $status);
 break;
 }
}
/** 
 * Handle a new client connection
 */
function handle_client($ssock, $csock)
{
 GLOBAL $__server_listening;
 $pid = pcntl_fork();
 if ($pid == -1)
 {
 /* fork failed */
 echo "fork failure!\n";
 die;
 }elseif ($pid == 0)
 {
 /* child process */
 $__server_listening = false;
 socket_close($ssock);
 interact($csock);
 socket_close($csock);
 }else
 {
 socket_close($csock);
 }
}
function interact($socket)
{
 /* TALK TO YOUR CLIENT */
}
/**
 * Become a daemon by forking and closing the parent
 */
function become_daemon()
{
 $pid = pcntl_fork();
 
 if ($pid == -1)
 {
 /* fork failed */
 echo "fork failure!\n";
 exit();
 }elseif ($pid)
 {
 /* close the parent */
 exit();
 }else
 {
 /* child becomes our daemon */
 posix_setsid();
 chdir('/');
 umask(0);
 return posix_getpid();
 }
}
?>
up
19
Boylett
18 years ago
If you want to have multiple clients on a server you will have to use non blocking.
<?php
$clients = array();
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'127.0.0.1',$port);
socket_listen($socket);
socket_set_nonblock($socket);
while(true)
{
 if(($newc = socket_accept($socket)) !== false)
 {
 echo "Client $newc has connected\n";
 $clients[] = $newc;
 }
}
?>
up
4
Greg MacLellan
22 years ago
The socket returned by this resource will be non-blocking, regardless of what the listening socket is set to. This is actually true for all FCNTL modifiers.
up
2
renmengyang567 at gmail dot com
7 years ago
<explain>
 This case is a very simple interaction between the TCP client side and the TCP server side
<?php
// create for simple-tcp-server
$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
socket_bind($sock, '127.0.0.1',5000);
socket_listen($sock,1);
$clnt_sock = socket_accept($sock); //阻塞
$st = "hello world ^_^";
socket_write($clnt_sock, $st,strlen($st));
socket_close($clnt_sock);
socket_close($sock);
?>

<?php
//create for simple-tcp-client 
$clnt_sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
socket_connect($clnt_sock, '127.0.0.1', 5000);
$ret= socket_read($clnt_sock, 1024);
print "from simple-tcp-server:".$ret.PHP_EOL;
socket_close($clnt_sock);
?>

<fruit>
from simple-tcp-server:hello world ^_^
up
-3
gmkarl at gmail dot com
19 years ago
Be aware signal handler functions set with pcntl_signal are not called while a socket is blocking waiting for a connection; the signal is absorbed silently and the handler called when a connection is made.
+add a note

AltStyle によって変換されたページ (->オリジナル) /