PHP Doku:: Akzeptiert eine Verbindung an einem Socket - function.socket-accept.html

Verlauf / Chronik / History: (2) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzSonstige DiensteSocketsSocket-Funktionensocket_accept

Ein Service von Reinhard Neidl - Webprogrammierung.

Socket-Funktionen

<<Socket-Funktionen

socket_bind>>

socket_accept

(PHP 4 >= 4.1.0, PHP 5)

socket_acceptAkzeptiert eine Verbindung an einem Socket

Beschreibung

resource socket_accept ( resource $socket )

Nachdem der Socket socket mit socket_create() erzeugt, mit socket_bind() mit einem Namen verknüpft und mit socket_listen() angewiesen wurde, nach hereinkommenden Verbindungsanforderungen zu horchen, werden sie mit dieser Funktion an dem Socket zugelassen. Nach einem erfogreichen Verbindungsaufbau wird ein neuer Socket-Deskriptor zurückgegeben, welcher zur Kommunikation benutzt werden kann. Gibt es mehrere Verbindungen an diesem Socket, werden diese in eine Warteschlange gestellt und die erste Verbindung wird benutzt. Falls es keine wartenden Verbindungen gibt, blockiert die Funktion socket_accept() so lange, bis eine Verbindung angefordert wird. Falls der Socket socket mit den Funktionen socket_set_blocking() oder socket_set_nonblock() auf 'nicht blockieren' gesetzt wurde, wird FALSE zurückgegeben.

Der Socket-Deskriptor, der von socket_accept() zurückgegeben wird, sollte nicht dazu benutzt werden, neue Verbindungen zuzulassen. Der ursprüngliche wartende Socket socket bleibt dagegen geöffnet und kann wiederverwendet werden.

Parameter-Liste

socket

Ein gültiger Socket-Deskriptor, der von der Funktion socket_create() erzeugt wurde.

Rückgabewerte

Gibt bei Erfolg einen neuen Socket-Deskriptor zurück oder FALSE, falls ein Fehler auftritt. Der aktuelle Fehlercode kann mit der Funktion socket_last_error() ermittelt werden. Dieser Fehlercode kann an die Funktion socket_strerror() übergeben werden, um eine textuelle Beschreibung des Fehlers zu erhalten.

Siehe auch


9 BenutzerBeiträge:
- Beiträge aktualisieren...
alan at binarystars dot com
17.04.2009 4:42
Beware 'socket_accept' does not return false; instead it returns NULL on error:

<?php
       
# accept the client and create a new socket
       
if (($new_socket = @socket_accept($master_socket))===false) {
            echo
"I should be here; but I'm not.";
        }
       
var_dump($master_socket);
       
var_dump($new_socket);
?>

==================
CLI OUTPUT:
array(1) {
  [0]=>
  resource(20) of type (Socket)
}
NULL
==================
Where $master_socket should be a single resource.
Anonymous
10.05.2008 1:32
If you want to know the remote address ( ip address ) and the port of an incoming connection that has been accepted with socket_accept(), you can use socket_getpeername()
Boylett
18.04.2008 18:01
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;
    }
}

?>
lars at opdenkamp dot eu
29.01.2008 13:35
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();

    }
}

?>
galantonp at yahoo dot com
13.06.2007 19:20
socket_accept with timeout, seems to work for me on Apache/1.3.37 (FreeBSD 6.0) PHP/4.4.7.

Adapted from ScriptBlue at nyc dot rr dot com's post under socket_connect.

<?php
$socket
= socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,$address,$port);
socket_listen($socket);

echo
"Waiting for a connection\n";
$conn = false;
switch(@
socket_select($r = array($socket), $w = array($socket), $e = array($socket), 60)) {
    case
2:
        echo
"Connection refused\n";
        break;
    case
1:
        echo
"Connection accepted\n";
       
$conn = @socket_accept($socket);
        break;
    case
0:
        echo
"Connection timed out\n";
        break;
}
   
   
if (
$conn !== false) {
   
// communicate over $conn
}

 
?>
gmkarl at gmail dot com
22.05.2007 18:15
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.
simon at 180solutions dot com
16.05.2005 17:11
>Accepting a connection using php-sockets:
>
>$fd = socket_create(AF_INET, SOCK_STREAM, 6 /* OR >getprotobyname("TCP")*/);
>
>$PORT = 5000;
>
>socket_bind($fd, "0.0.0.0", $PORT);
>
>while(true)
>{
>$remote_fd = socket_accept($fd);
>
>remote_socket_client_handle($remote_fd);
>
>}
>
>It is simple!

This example doesn't work. You have to call socket_listen($fd) after your bind in order to accept incoming connections.

Simon
Greg MacLellan
11.12.2003 21:49
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.
diogo at transoft dot com dot br
18.08.2003 22:32
Accepting a connection using php-sockets:

$fd = socket_create(AF_INET, SOCK_STREAM, 6 /* OR getprotobyname("TCP")*/);

$PORT = 5000;

socket_bind($fd, "0.0.0.0", $PORT);

while(true)
{
$remote_fd = socket_accept($fd);

remote_socket_client_handle($remote_fd);

}

It is simple!



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)