server端代码 如下:<?php
set_time_limit(0);
 
$host = "127.0.0.1";
$port = 12345;
 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n"); // 创建一个Socket
 
$result = socket_bind($socket, $host, $port) or die("Could not bind tosocket\n"); //绑定Socket到端口
 
$result = socket_listen($socket) or die("Could not set up socket listener\n"); // 开始监听连接
 
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n"); // 处理通信//若换成循环接收数据,客户端将一直处理等待接收状态
$input = socket_read($spawn, 1024) or die("Could not read data\n");
/* 
while (( $data = socket_read($spawn, 1024)) != false) 
$input .= $data;
*/ echo 'input:', strlen($input), "\n";
 
$output = date("Y-m-d H:i:s"). "\n"; //处理客户端输入并返回结果
 
echo "output:", $output, "\n";
 
// 数据传送 向客户端写入返回结果
socket_write($spawn, $output, strlen($output)) or die("Could not write output\n");
 
// 关闭sockets
socket_close($spawn);
socket_close($socket);client端, 代码如下:<?phpset_time_limit(0);
 
$host = "127.0.0.1";
$port = 12345;
 
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socket\n"); // 创建一个Socket
 
$connection = socket_connect($socket, $host, $port) or die("Could not connet server\n");    //  连接
 
socket_write($socket, "time") or die("Write failed\n"); // 数据传送 向服务器发送消息echo 'wait for data';while (($buffer = socket_read($socket, 1024))!=false) {
    echo("Data sent was: time\nResponse was:" . $buffer . "\n");
}
 
socket_close($socket);如果将server端对client read操作换成循环内部读取,则client会一直处于 wait data状态。
有办法让server端循环读的情况下,读完后给client写数据吗sockettcpphpserver

解决方案 »

  1.   

    你这个循环没有错,但是一次数据发送完成就关闭socket连接了,没有循环的必要吧。
      

  2.   


    <?php
    set_time_limit(0);
     
    $host = "127.0.0.1";
    $port = 12345;
     
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n"); // 创建一个Socket
     
    $result = socket_bind($socket, $host, $port) or die("Could not bind tosocket\n"); //绑定Socket到端口
     
    $result = socket_listen($socket) or die("Could not set up socket listener\n"); // 开始监听连接
     
    $spawn = socket_accept($socket) or die("Could not accept incoming connection\n"); // 处理通信//若换成循环接收数据,客户端将一直处理等待接收状态
    $input = socket_read($spawn, 1024) or die("Could not read data\n");
     
    while (( $data = socket_read($spawn, 1024)) != false) 
    { $input .= $data;
    echo 'input:', strlen($input), "\n";
     
    $output = date("Y-m-d H:i:s"). "\n"; //处理客户端输入并返回结果
     
    echo "output:", $output, "\n";
     
    // 数据传送 向客户端写入返回结果
    socket_write($spawn, $output, strlen($output)) or die("Could not write output\n");
     }
    // 关闭sockets
    socket_close($spawn);
    socket_close($socket);
      

  3.   


    <?php
    set_time_limit(0);
     
    $host = "127.0.0.1";
    $port = 12345;
     
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n"); // 创建一个Socket
     
    $result = socket_bind($socket, $host, $port) or die("Could not bind tosocket\n"); //绑定Socket到端口
     
    $result = socket_listen($socket) or die("Could not set up socket listener\n"); // 开始监听连接
     
    $spawn = socket_accept($socket) or die("Could not accept incoming connection\n"); // 处理通信//若换成循环接收数据,客户端将一直处理等待接收状态
    $input = socket_read($spawn, 1024) or die("Could not read data\n");
     
    while (( $input = socket_read($spawn, 1024)) != false) 
    {

    echo 'input:', strlen($input), "\n";
     
    $output = date("Y-m-d H:i:s"). "\n"; //处理客户端输入并返回结果
     
    echo "output:", $output, "\n";
     
    // 数据传送 向客户端写入返回结果
    socket_write($spawn, $output, strlen($output)) or die("Could not write output\n");
    }
    // 关闭sockets
    socket_close($spawn);
    socket_close($socket);
      

  4.   

    这个只是个demo,实际情况下,client发过来的数据不定长,所以只能循环接收
      

  5.   

    读循环里面确实不应该用PHP_NORMAL_READ这个选项
    去掉PHP_NORMAL_READ这个选项也不能解决问题,有解决方法吗
      

  6.   

    while (true) {
        $msg = socket_accept ($socket);               // 接受一个SOCKET
        if (!$msg) {
            echo "socket_accept() failed:".socket_strerror ($msg)."\n";
            break;
        }
        while (true) {
            $command = strtoupper (trim (socket_read ($msg, 1024))); //等待客户端数据
            if (!$command) break;
            //相关处理,比如直接回显
            socket_write ($msg, $command, strlen ($command));
        }
        socket_close ($msg);
        if ($command == "QUIT") //如果收到的是通讯结束
            break;
    }
    socket_close ($socket);                   // 关闭SOCKET
      

  7.   

    读循环里面确实不应该用PHP_NORMAL_READ这个选项
    去掉PHP_NORMAL_READ这个选项也不能解决问题,有解决方法吗
    我都是用流函数实现的。
    <?php/*
     * 不使用apache,cli模式
     * 命令接收端
     * 单用户,即单连接
     *//**
     * 命令接收端Messenger
     * 单线程
     */
    class SocketServer {    protected $ip;
        protected $port;
        protected $webSocket;
        protected $users;
        protected $userIndex = 0;
        protected $message;    public function __construct($ip = "127.0.0.1", $port = 12345) {
            $this->ip = $ip;
            $this->port = $port;
            //
            self::init();
            //
            $this->createServer();
            $this->log('listenning user...');
            $this->listenningUser();
        }    protected function createServer() {
            $errno;
            $errstr;
            $this->webSocket = stream_socket_server("tcp://" . $this->ip . ':' . $this->port, $errno, $errstr);
            if (!$this->webSocket) {
                self::log("$errstr ($errno)");
                exit();
            }
            $this->log('server ok .');
        }    protected function listenningUser() {
            while (true) {
                $this->userIndex++;
                $user = $this->users[$this->userIndex] = stream_socket_accept($this->webSocket, 9999999999);
                //
                if (is_resource($this->users[$this->userIndex - 1])) {
                    $u = $this->users[$this->userIndex - 1];
                    $u->close();
                    $u = NULL;
                    unset($this->users[$this->userIndex - 1]);
                }
                //
                $this->log('连入新用户');
                $this->listenningMessage();
            }
        }    protected function listenningMessage() {
            while (is_resource($this->users[$this->userIndex])) {
                $this->message = stream_socket_recvfrom($this->users[$this->userIndex], 10270000);
                if (!$this->message) {
                    $this->closeUser();
                    break;
                }
                $this->messageOperate();
            }
        }    function messageOperate() {
            $this->log("收到消息:");
            $this->log($this->message);
            //mb_strstr($haystack, $needle, $before_needle, $encoding)
            $this->sendMessage('done');
        }    function sendMessage($msg) {
            if($msg===''){
                return -1;
            }
            return stream_socket_sendto($this->users[$this->userIndex], $msg);
        }    public function closeUser() {
            if (!is_resource($this->users[$this->userIndex]))
                return FALSE;
            @stream_socket_shutdown($this->users[$this->userIndex], STREAM_SHUT_RDWR);
            @fclose($this->users[$this->userIndex]);
            $this->log("用户连接断开.");
            return TRUE;
        }    public function shutdown() {
            stream_socket_shutdown($this->webSocket, STREAM_SHUT_RDWR);
            fclose($this->webSocket);
        }    protected static function init() {
            error_reporting(E_ALL ^ E_NOTICE);
            set_time_limit(0);
            ob_implicit_flush();
            date_default_timezone_set('Asia/Shanghai');
            ignore_user_abort(TRUE);
            mb_internal_encoding('gbk');
        }    protected static function log($message) {
            echo "\r\n" . $message . "\r\n";
        }}
    $server = new SocketServer();
    <?php/*
     * 不使用apache,cli模式
     * 客户端
     */class SocketClient {    protected $client;
        protected $message;    public function __construct($domain,$port) {
            $this->init();
            $this->client = stream_socket_client("tcp://$domain:$port", $errno, $errstr, 300000);
            if (!$this->client) {
                $this->log("$errstr ($errno)");
                return FALSE;
            }
            $this->log('client ok');
        }    protected static function init() {
            error_reporting(E_ALL ^ E_NOTICE);
            //error_reporting(0);
            set_time_limit(0);
            ob_implicit_flush();
            date_default_timezone_set('Asia/Shanghai');
            ignore_user_abort(TRUE);
            mb_internal_encoding('gbk');
        }    public function sendMessage($msg) {
            if ($msg === '') {
                return -1;
            }
            try {
                stream_socket_sendto($this->client, $msg);
            } catch (Exception $exc) {
                //$this->log($exc->getTraceAsString());
            }
        }    public function getMessage() {
            $this->message = stream_socket_recvfrom($this->client, 10270000);
            //$this->log("收到消息:");
            //$this->log($this->message);
            fwrite(STDOUT, $this->message . "\r\n");
        }    public function shutdown() {
            stream_socket_shutdown($this->client, STREAM_SHUT_RDWR);
            fclose($this->client);
        }    public static function log($message) {
            echo "\r\n" . $message . "\r\n";
        }}//$client = new SocketClient('127.0.0.1',12345);
    while (true) {    $msg = fread(STDIN, 9999999);
        if (!trim($msg)) {
            continue;
        }
        $client->sendMessage($msg);
        $client->getMessage();
    }
      

  8.   

    版主好
    这里我需要读取完client放的数据分析后才能write回client端,你想让client那边发送quit命令结束socket,这个在线上环境不能实现。还有更好的办法吗?多谢各位!!