unix网络io模型之阻塞模型

Posted weixin_44183558

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unix网络io模型之阻塞模型相关的知识,希望对你有一定的参考价值。

自己手写的五种网络模型,欢迎各路大神提意见和建议;

环境准备:php7.4,swoole4.8.2,(这里我用的是mac)

        homebrew安装:mac下国内安装Homebrew教程 - 阿圣枫 - 博客园

        php安装:mac下安装php7.4+mysql5.7+nginx环境_且行好事莫问前程-CSDN博客

        swoole安装:Swoole4 文档,我用的是pecl,mac安装可能会出现小问题,可以评论留言

这里使用composer来管理我们的命令空间

        composer安装:Composer 安装与使用 | 菜鸟教程,找到对应的安装方式

创建一个新的文件夹,执行composer init初始化一下;(一直回车,没有信息的要填一下信息)

 初始化成功,生成了以下文件和文件夹

 我这里修改了composer.json里的命名空间,需要执行composer dump-autoload命令,重新生成autoload文件,不然会找不到类

先创建下图的文件和文件夹

首先是workerbase.php是一个抽象基础类,定义一些基本的方法

<?php
namespace Ztms;

/**
 * 基础抽象类
 */
abstract class WorkerBase

    protected $server;

    protected $events = [];

    protected $config;

    protected $type = "tcp";

    public function __construct($host, $port)
    
        //建立socket
        $this->server = stream_socket_server("tcp://".$host.":".$port);
        // echo "tcp://".$host.":".$port."\\n";
        var_dump("tcp://".swoole_get_local_ip()['en0'].":".$port."启动服务");
    

    /**
     * 不同的模型实现不一样
     * @var [type]
     */
    protected abstract function accept();

     /**
     * 添加事件
     * @method on
     * @param  [type] $event [description]
     * @param  [type] $call  [description]
     * @return [type]        [description]
     */
    public function on($event, $call)
    
        $this->events[strtolower($event)] = $call;
    

    public function set()

    /**
     * 发送信息
     * @method send
     * @param  [type] $client [description]
     * @param  [type] $data   [description]
     * @return [type]         [description]
     */
    public function send($client, $data)
    
        fwrite($client, $data);
        // \\fread
    

    public function close($client)
    
        \\fclose($client);
    

    public function start()
    
        // var_dump($this->events);
        // var_dump($this->events, "输出服务注册的事件");
        
        $this->accept();
    

 worker.php就是阻塞模型,这while是让他一直保持监听状态

<?php
namespace Ztms\\Blocking;

use Ztms\\WorkerBase;
/**
 * 阻塞模型
 */
class Worker extends WorkerBase

    protected function accept()
    
        while (true) 
            // 监听是否存在连接
            $conn = stream_socket_accept($this->server);
            
            if (!empty($conn)) 
                // 触发建立连接事件
                $this->events['connect']($this, $conn);

                // 接收服务的信息
                $data = fread($conn, 65535);
                $this->events['receive']($this, $conn, $data);
            

             if (!empty($conn) && \\get_resource_type($conn) == "Unknown") 
                // 断开连接
                $this->events['close']($this, $conn);
             
        
    

server.php是服务端

<?php

require_once __DIR__."/../../vendor/autoload.php";

use Ztms\\Blocking\\Worker;

$server = new Worker('0.0.0.0', 9500);

$server->on('connect', function($server, $client)
    echo "1我们连接成功啦"."\\n";
);

$server->on('receive', function(Worker $server, $client, $data)
    //接受客户端消息
    echo '2'.$data."\\n";
    //服务端发送给客户端
    $server->send($client, "3滚,你这个渣男,你对别人也是这么说的吧");
    sleep(20);//为了更好的看到效果,这里假装睡眠20秒
    $server->close($client);
);

$server->on('close', function($server, $client)
    echo "4客户端只好断开了连接"."\\n";
);
$server->start();

client.php是客户端

<?php

require_once __DIR__."/../../vendor/autoload.php";
// 连接服务端
$fp = stream_socket_client("tcp://192.168.0.102:9500");

fwrite($fp, "一直有句话想对你说 做我的女朋友吧!");

var_dump(fread($fp, 65535));

ok,现在我们启动一下服务,进入test/blocking目录执行php server.php

 服务启动成功,再打开两个窗口,都进入到test/blocking目录,同时执行time php client.php

可以看到右上角的客户端已经收到服务端发来的消息了,服务端我们已经设置了20秒关闭连接,所以右下角的客户端必须等待右上角客户端的连接关闭才能执行,右上的客户端已经执行完毕了,就开始执行右下角的,如图

 到此已经测试成功了,在这里我只想说,阻塞模型并不是渣男,他的确是对很多人说了做我女朋友吧,但是都是在分手之后说的,所以他并不是一个渣男。

以上是关于unix网络io模型之阻塞模型的主要内容,如果未能解决你的问题,请参考以下文章

透彻Linux(Unix)五种IO模型

Unix网络编程中的五种IO模型

网络IO之阻塞非阻塞同步异步总结

Unix下IO模型及他们之间的区别

网络通信模型(IO模型)学习摘要

linux网络IO模型——阻塞非阻塞和同步异步