写代码写的多了以后发信啊很多事情都是套路,或者定式,前人总结的经验很牛逼.
城市套路深,赶紧回农村,农村路也滑,人心更复杂.
对于像服务器这种既要求较好的实时性,又要求能同时处理多个客户端请求的程序,应该同时使用同步线程和异步线程的方式来实现,既半同步/半异步模式.
1.半同步/半反应堆模式
异步线程只有一个,由主线程来充当.它负责监听所有socket上的事件.
(1)如果监听socket上有可读事件发生,即有新的连接请求到来,主线程就接收连接得到新的连接socket,然后往epoll内核事件表中注册该连接socket的读写事件.
(2)如果连接socket上有读写事件发生,则有新的客户请求到来,或者有数据要发送,主线程就将该连接socket插入到请求队列中.
(3)所有工作线程都睡眠在请求队列上,当有任务到来时,会有一定的算法或机制来唤醒工作线程来处理新连接的请求.
缺点:
缺点1:主线程和工作线程操作队列,需要加锁保护,会耗费一定的cpu资源.
缺点2:如果客户数量多,而工作线程较少,处理客户端请求的能力有限,会导致清楚队列中堆积很多任务对象,客户端的响应速度将越来越慢.如果通过增加工作线程来解决这一问题,则工作线程的切换也将耗费大量cpu时间.
如图所示:
这种模式下工作线程不负责连接socket的可读可写事件的注册问题.
2.更高效点的半同步/半异步模式
和上面模式不同的是,
(1)主线程只负责管理侦听socket,
(2)连接socket由工作线程来管理.
(3)当有新的连接到来时,主线程将返回的连接socket派发到工作线程,
(4)该新连接socket上的任何IO操作都由后续指定的工作线程来处理,直到客户关闭连接.
工作线程自己注册连接socket的读写事件到自己的epoll内核事件表中.
如图所示:
3.领导者-追随者模式
1. 有若干个线程(一般组成线程池)用来处理大量的事件
2. 有一个线程作为领导者,等待事件的发生;其他的线程作为追随者,仅仅是睡眠。
3. 假如有事件需要处理,领导者会从追随者中指定一个新的领导者,自己去处理事件。
4. 唤醒的追随者作为新的领导者等待事件的发生。
5. 处理事件的线程处理完毕以后,就会成为追随者的一员,直到被唤醒成为领导者。
6. 假如需要处理的事件太多,而线程数量不够(能够动态创建线程处理另当别论),则有的事件可能会得不到处理。
领导者-追随者模式和半同步半异步模式的最大区别是,半同步半异步模式有一个显式的待处理事件队列,被休眠的工作线程不断的被唤醒去处理队列中的任务.
领导者-追随者模式暂时还没有遇到,初步了解下.
3.有限状态机
下面来介绍一种逻辑单元内部的高效编程方法,有限状态机
有的应用称协议头部包含数据包类型字段,每种类型可以映射为一种执行流程.
写远控软件的时候,会有个消息收发中心,专门用于解析各种协议数据包,如获取文件列表.进程监控数据包,视频通信数据包等等,其实可以做成状态机的形式.开源项目EasyDarwin对于RTSP流的处理就是采用状态机的形式.在看状态机相关代码时,有几个重点:1.清楚状态机有几种状态2.各个状态之间的状态转移