php socket编程 读完成后写阻塞

jiuw0902 2013-09-24 03:59:53
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端, 代码如下:

<?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

$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写数据吗



...全文
361 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
jdgdf566 2013-09-29
  • 打赏
  • 举报
回复
引用 10 楼 jiuw0902 的回复:
那位大神能帮忙解决一下这个问题,顶一下
我没解决你的问题?
jiuw0902 2013-09-26
  • 打赏
  • 举报
回复
那位大神能帮忙解决一下这个问题,顶一下
jdgdf566 2013-09-25
  • 打赏
  • 举报
回复
引用 6 楼 jiuw0902 的回复:
[quote=引用 3 楼 jdgdf566 的回复:]

<?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);
读循环里面确实不应该用PHP_NORMAL_READ这个选项 去掉PHP_NORMAL_READ这个选项也不能解决问题,有解决方法吗[/quote] 我都是用流函数实现的。
<?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();
}

xuzuning 2013-09-25
  • 打赏
  • 举报
回复
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
jiuw0902 2013-09-25
  • 打赏
  • 举报
回复
引用 7 楼 xuzuning 的回复:
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
版主好 这里我需要读取完client放的数据分析后才能write回client端,你想让client那边发送quit命令结束socket,这个在线上环境不能实现。还有更好的办法吗?多谢各位!!
jiuw0902 2013-09-25
  • 打赏
  • 举报
回复
引用 3 楼 jdgdf566 的回复:

<?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);
读循环里面确实不应该用PHP_NORMAL_READ这个选项 去掉PHP_NORMAL_READ这个选项也不能解决问题,有解决方法吗
jiuw0902 2013-09-25
  • 打赏
  • 举报
回复
引用 1 楼 linux_PHP_ 的回复:
你这个循环没有错,但是一次数据发送完成就关闭socket连接了,没有循环的必要吧。
这个只是个demo,实际情况下,client发过来的数据不定长,所以只能循环接收
jdgdf566 2013-09-25
  • 打赏
  • 举报
回复

<?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);
jdgdf566 2013-09-25
  • 打赏
  • 举报
回复

<?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);
Hx_Moon_ 2013-09-24
  • 打赏
  • 举报
回复
你这个循环没有错,但是一次数据发送完成就关闭socket连接了,没有循环的必要吧。

21,893

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧