PHP 8.5.0 Alpha 1 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

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.

Ver también

add a note

User Contributed Notes 5 notes

up
25
lars at opdenkamp dot eu
17 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
17 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
21 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
6 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
-1
gmkarl at gmail dot com
18 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.
To Top