appserv apache+php写的socket服务器不回应问题,单个单个客户端连接上没问题能收到回应(速度很快),为什么同时多个(大概200个)客户端连接时服务器就不给回应了~~
高手进来指点!!!谢谢!!!

解决方案 »

  1.   

    加大 apache 的 并发连接数....
      

  2.   

    哦,php的socket监听是单线程的,而且是堵塞式的··· 意思就是说,有一个用户正在访问你的socket端口,那么其它用户就必须等待。所以,用户一多,就会没反映了。
      

  3.   

    php是单线程的没错,通过轮巡的方式处理连接我有设置成非阻塞~
      

  4.   

    设置成非阻塞:socket_set_nonblock
    (PHP 4 >= 4.1.0, PHP 5)socket_set_nonblock — Sets nonblocking mode for file descriptor fd 说明
    bool socket_set_nonblock ( resource $socket )
    The socket_set_nonblock() function sets the O_NONBLOCK flag on the socket specified by the socket parameter. When an operation (e.g. receive, send, connect, accept, ...) is performed on a non-blocking socket, the script not pause its execution until it receives a signal or it can perform the operation. Rather, if the operation would result in a block, the called function will fail. 参数socket 
    A valid socket resource created with socket_create() or socket_accept(). 
    返回值
    成功时返回 TRUE, 或者在失败时返回 FALSE. 范例Example #1 socket_set_nonblock() example<?php
    $socket = socket_create_listen(1223);
    socket_set_nonblock($socket);socket_accept($socket);
    ?> 
    This example creates a listening socket on all interfaces on port 1223 and sets the socket to O_NONBLOCK mode. socket_accept() will immediately fail unless there is a pending connection exactly at this moment. 
      

  5.   

    如果还是响应不过来,建议检查一下web server的连接数,另外看一下是否有其他比较消耗资源的操作
      

  6.   


    PHP是单线程的,只有当一个SOCKET客户完成服务后,才能接收下一个,参考:
    用 Socket 和 Pcntl 实现一个多线程服务器    要建立一个简单的服务,如果不考虑性能方面的问题,比如并发100 左右的服务,可以简单的用 Socket + Pcntl。
     来实现,我准备写一个系列的教程,让新手就能进行编写socket 服务。
        下面要实现的是这样一个服务,就是能进行加减乘除的四则运算。数字可以是任意大的数。可以用下面的命令测试这个服务:
    telnet 122.224.124.251 8086
    就会进入下面的界面:
     Welcome to the PHP Test Server. To quit, type 'quit'.
    #输入quit 就可以退出。
    下面演示功能:
    输入: 11111111111111111111111 * 222222222222222222222222222# 11111111111111111111111 * 222222222222222222222222222
    # result is : 2469135802469135802469111108641975308641975308642.
    就能把结果计算出来。这个演示的服务,可以多个人同时进行 运算。这个或许就是一个基本的多线程服务,比如,web服务器
    就是一个多线程服务,但是,它要处理大量线程,进程的并发问题。所以比较复杂。
    下面是代码, 具体的解释就在后面的教程中了。这个类是处理的是进程控制,具体的逻辑处理封装在了 clientHandle 这个回调函数里面。通过修改这个回调
    函数的内容,你也能很快的定制一个自己的服务器。
    <?php
    class Simple_Server 
    {   
        private $sock;
        
        private $csock;
        
        private $isListen = true;
        
        private $callback;
        
        private $user;
        
        private $uid;
        
        private $gid;
        
        private $userHome;
        
        
        private $scriptName = "simple-server";
        
        
        
        /**
         * use $user set the user run the script.
         * fock a thread, init the socket, and wait user to request.
         *
         */
        function __construct($callback, $ip = '127.0.0.1', $port = '8086',$user = 'daemon')
        {
            error_reporting(E_ALL); 
            ini_set("display_errors", 0);
            set_time_limit(0); 
            ob_implicit_flush();
            declare(ticks = 1);
            $this->callback = $callback;
            $this->user = $user;
            
            $this->getUserInfo();
            $this->changeIdentity();
            $this->daemon();        pcntl_signal(SIGTERM, array($this, 'sigHandler'));
            pcntl_signal(SIGINT,  array($this, 'sigHandler'));
            pcntl_signal(SIGCHLD, array($this, 'sigHandler'));        $this->run($ip, $port);
        }    function run($address, $port) 
        { 
            if(($this->sock = socket_create(AF_INET, SOCK_STREAM, 0)) === false) 
            { 
                $this->error("failed to create socket: ".socket_strerror($this->sock)); 
            }
            
            $sock = $this->sock;
            
            if(($ret = socket_bind($sock, $address, $port)) === false) 
            { 
                $this->error("failed to bind socket: ".socket_strerror($ret));
            }        if(($ret = socket_listen($sock, 0)) === false) 
            { 
                $this->error("failed to listen to socket: ".socket_strerror($ret));
            }        socket_set_nonblock($sock);         $this->log("waiting for clients to connect");        while ($this->isListen) 
            { 
                $this->csock = @socket_accept($sock); 
                if ($this->csock === false) 
                { 
                    usleep(1000); //1ms
                } else if ($this->csock > 0) {
                    $this->client(); 
                } else { 
                    $this->error("error: ".socket_strerror($this->csock));
                }
            }
        }    /** 
          * Handle a new client connection 
          */ 
        function client()
        { 
            $this->log('begin client');
            $ssock = $this->sock;
            $csock = $this->csock;
            $pid = pcntl_fork(); 
            if ($pid == -1) 
            {
                $this->error("fock clinet child error.");
            } else if ($pid == 0)  {
                $pid = posix_getpid();
                $this->log("begin client child ($pid).");
                /* child process */ 
                $this->isListen = false;
                $this->log("close sock in child");
                socket_close($ssock);
                $this->log("begin handle user logic.");
                $callback = $this->callback;
                call_user_func($callback, $csock, $this);
                $this->log("end handle user logic.");
                $this->log("close client sock in child.");
                socket_close($csock);
                $this->log("end client");
            } else  {
                $this->log("close csock in child");
                socket_close($csock); 
            }
        }    function __destruct()
        {
            @socket_close($this->sock);
            @socket_close($this->csock);
            $pid = posix_getpid();
            $this->log("end daemon in __destruct pid($pid).");
        }    function getUserInfo()
        {
            $uid_name = posix_getpwnam($this->user);
            $this->uid = $uid_name['uid'];
            $this->gid = $uid_name['gid'];
            $this->userHome = $uid_name['dir'];
        }    function changeIdentity() 
        {
            if(!posix_setuid($this->uid)) 
            { 
                $this->error("Unable to setuid to " . $this->uid); 
            }
        }    /** 
         * Signal handler 
         */ 
        function sigHandler($sig) 
        { 
            switch($sig) 
            { 
                case SIGTERM: 
                case SIGINT: 
                    exit();
                break;             case SIGCHLD: 
                    pcntl_waitpid(-1, $status); 
                break;
            }
        }    function error($msg)
        {
            $str = date("Y-m-d H:i:s") . " " . $msg . "\n";
            file_put_contents(dirname(__FILE__) . "/error.log", $str, FILE_APPEND);
            exit(0);
        }    function log($msg)
        {
            $str = date("Y-m-d H:i:s") . " " . $msg . "\n";
            file_put_contents(dirname(__FILE__) . "/message.log", $str, FILE_APPEND);
        }    function daemon() 
        { 
            $ppid = posix_getpid();
            $this->log("begin parent daemon pid ($ppid)");
            $pid = pcntl_fork(); 
            if ($pid == -1) 
            {
                /* fork failed */ 
                $this->error("fork failure!"); 
            } else if ($pid) { 
                /* close the parent */
                $this->log("end parent daemon pid($ppid) exit.");
                exit(); 
            } else  { 
                /* child becomes our daemon */ 
                posix_setsid(); 
                chdir($this->userHome);
                umask(0);
                $pid = posix_getpid();
                $this->log("begin child daemon pid($pid).");
            }
        }
    }function clientHandle($msgsock, $obj)
    {
        /* Send instructions. */
        $br = "\r\n";
        $msg = "$br Welcome to the PHP Test Server. $br $br To quit, type 'quit'.$br# ";    $obj->log($msg);
        socket_write($msgsock, $msg, strlen($msg));
        $nbuf = '';
        socket_set_block($msgsock);
        bcscale(4);  // defalult 4 eg. 1 + 2.00001 = 3
        do {
            if (false === ($nbuf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
                $obj->error("socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)));
            }        if (!$nbuf = trim($nbuf)) {
                continue;
            }        if ($nbuf == 'quit') {
                break;
            }
            if ($nbuf == 'shutdown') {
                break;
            }
            
            if (empty($nbuf)) continue;
            
            preg_match("/([\d.]+)[\s]*([+\-*\/x])[\s]*([\d.]+)/i", $nbuf , $matches);
            $op   = @$matches[2];
            $left = @$matches[1];
            $right = @$matches[3];        $result = NULL;
            if ($op == "+") {
                $result = bcadd($left, $right);
            } else if ($op == "-") {
                $result = bcsub($left, $right);
            } else if ($op == "x" || $op == "x" || $op == "*") {
                $result = bcmul($left, $right);
            } else if ($op == "/") {
                $result = bcdiv($left, $right);
            } else {
                $talkback = "# error: expression \"$nbuf\" error.$br# ";
            }
            if ($result === NULL) {
                socket_write($msgsock, $talkback, strlen($talkback));
            } else {
                $result = rtrim($result, ".0");
                $talkback = "# result is : $result.$br# ";
                socket_write($msgsock, $talkback, strlen($talkback));
            }
            $nbuf = '';
        } while (true);
    }$server = new Simple_Server("clientHandle", "122.224.124.251");
    ?>