文字

socket_accept

(PHP 4 >= 4.1.0, PHP 5)

socket_acceptAccepts a connection on a socket

说明

resource socket_accept ( resource $socket )

After the socket socket has been created using socket_create() , bound to a name with socket_bind() , and told to listen for connections with socket_listen() , this function will accept incoming connections on that socket. Once a successful connection is made, a new socket resource is returned, which may be used for communication. If there are multiple connections queued on the socket, the first will be used. If there are no pending connections, socket_accept() will block until a connection becomes present. If socket has been made non-blocking using socket_set_blocking() or socket_set_nonblock() , FALSE will be returned.

The socket resource returned by socket_accept() may not be used to accept new connections. The original listening socket socket, however, remains open and may be reused.

参数

socket

A valid socket resource created with socket_create() .

返回值

Returns a new socket resource on success, or FALSE on error. The actual error code can be retrieved by calling socket_last_error() . This error code may be passed to socket_strerror() to get a textual explanation of the error.

参见

  • socket_connect() - 开启一个套接字连接
  • socket_listen() - Listens for a connection on a socket
  • socket_create() - 创建一个套接字(通讯节点)
  • socket_bind() - 给套接字绑定名字
  • socket_strerror() - Return a string describing a socket error

用户评论:

[#1] mightyplow at gmail dot com [2014-05-18 14:47:30]

In order to make many clients connectable to the server, you have to set the accepted socket also to non-blocking. Otherwise the accepted connection will block further incoming connections.

while (true) {
    $newSock = @socket_accept($sock);

    if ($newSock) {
        echo 'client connected';

        socket_set_nonblock($newSock);
    }
}

[#2] Boylett [2008-04-18 09:01:29]

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;
    }
}

?>

[#3] lars at opdenkamp dot eu [2008-01-29 04:35:53]

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


$__server_listening true;

error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
declare(
ticks 1);

become_daemon();


change_identity(6553465534);


pcntl_signal(SIGTERM'sig_handler');
pcntl_signal(SIGINT'sig_handler');
pcntl_signal(SIGCHLD'sig_handler');


server_loop("127.0.0.1"1234);


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;
    }
}


function server_loop($address$port)
{
    GLOBAL 
$__server_listening;

    if((
$sock socket_create(AF_INETSOCK_STREAM0)) < 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) ) < )
    {
        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;
        }
    }
}


function sig_handler($sig)
{
    switch(
$sig)
    {
        case 
SIGTERM:
        case 
SIGINT:
            exit();
        break;

        case 
SIGCHLD:
            
pcntl_waitpid(-1$status);
        break;
    }
}


function handle_client($ssock$csock)
{
    GLOBAL 
$__server_listening;

    
$pid pcntl_fork();

    if (
$pid == -1)
    {
        

        
echo "fork failure!\n";
        die;
    }elseif (
$pid == 0)
    {
        

        
$__server_listening false;
        
socket_close($ssock);
        
interact($csock);
        
socket_close($csock);
    }else
    {
        
socket_close($csock);
    }
}

function 
interact($socket)
{
    

}


function become_daemon()
{
    
$pid pcntl_fork();
    
    if (
$pid == -1)
    {
        

        
echo "fork failure!\n";
        exit();
    }elseif (
$pid)
    {
        

        
exit();
    }else
    {
        

        
posix_setsid();
        
chdir('/');
        
umask(0);
        return 
posix_getpid();

    }
}

?>

[#4] gmkarl at gmail dot com [2007-05-22 09:15:16]

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.

[#5] simon at 180solutions dot com [2005-05-16 08:11:25]

>Accepting a connection using php-sockets:
>
>$fd = socket_create(AF_INET, SOCK_STREAM, 6 );
>
>$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

[#6] Greg MacLellan [2003-12-11 12:49:14]

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.

上一篇: 下一篇: