php多线程(php和java哪个好)
- 微博
- Qzone
- 微信
PHP实现reactor单线程网络模型
原创流浪剑客262021-05-08 23:12:24
在各种网络模型的文章中,我们常常能看到 reactor 网络模型。
它常常出现在很多软件与外部交互的网络部分,如:
redis使用reactor单线程网络IO模型。
kafka使用reactor多线程网络IO模型。
为什么需要使用网络IO模型
关于为什么要使用网络IO模型:大家需要理解一下用户态、内核态、阻塞、非阻塞、同步、异步、IO多路复用等知识。
简单来讲
在这里简单地讲,就是用户态程序没法直接操作网络IO设备,它需要发起系统调用,将控制权交给操作系统内核,内核将数据从网卡中读取数据,返回给用户态程序。在这个过程中用户态程序是等待还是不等待,内核处理的结果是怎样通知给用户程序,这就是网络IO模型可以作优化的地方。
根本原因
说到底就是优化CPU的执行时间片,不能让CPU闲着。
很重要
补充一点网络数据的 copy 操作不是CPU执行的,CPU只是初始化这个传输动作,具体数据的 copy 是由 DMA 设备来完成的。
PHP实现Reactor单线程网络模型
reactor单线程网络模型,使用到了IO多路复用的epoll模型,事件机制。操作系统需要安装libevent扩展,php需要安装event、sockets扩展。
测试例子
<?php$addr = "0.0.0.0"; $port = 8888;// 创建服务端 socket$listenFd = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);// 绑定$bindRe = socket_bind($listenFd, $addr, $port);if (!$bindRe) { die("socket bind error"); }// 监听$listenRe = socket_listen($listenFd, 100);if (!$listenRe) { die("socket listen error"); }global $eventArr, $eventBase;// 实例化基础事件句柄,相当与 epoll_create 操作$eventBase = new EventBase();// 绑定监听句柄,到基础事件句柄, 相当于 epoll_ctl 操作$event = new Event($eventBase, $listenFd, Event::PERSIST | Event::READ, "ep_accept"); $event->add();// 等待句柄就绪, 相当于 epoll_wait 操作$eventBase->loop();function ep_accept($listener) { global $eventBase, $eventArr; if (($client = socket_accept($listener)) !== false){ $tmp = "连接成功\n"; socket_write($client, $tmp, strlen($tmp)); // 绑定端socket,到基础事件句柄, 相当于 epoll_ctl 操作 $clientEvent = new Event($eventBase, $client, Event::PERSIST | Event::READ, "ep_read", $client); $clientEvent->add(); // event实例一定要存放在一个全局数组里面。如果去掉该行,客户端强制断开再连接,服务端无法正常收到消息 // 这里这一步我也不知道原因,注视掉确实会导致客户端断开 // 希望能看到这里的大佬,评论区告知在下原因。 // 欢迎交流 $eventArr[intval($client)] = $clientEvent; } }function ep_read($fd) { $buffer = socket_read( $fd, 250 ); $msg = "你说:{$buffer}"; socket_write( $fd, $msg, strlen( $msg ) ); }
启动服务
php ceshi.php
结果截图
reactor单线程网络模型
我实现的功能是客户端发什么消息,服务端将消息重新返回给客户端。
这里我开了两个客户端作测试。符合实验的预期。
我个人觉得学习是个人的事,我的文章侧重于抛出一些观点,然后用简单的例子去论证,从而引发大家的兴趣,文章之中很多都是我参考了很多资料之后最简要的说明。大家应该关注文章之中引发个人困惑的东西,然后去思考学习。