本文共 2402 字,大约阅读时间需要 8 分钟。
连接建立:服务器accept(被动)接受连接,客户端connect(主动)发起连接
连接断开:主动断开(close、shutdown),被动断开(read返回0,指对等端主动断开连接)
消息到达:文件描述符可读
消息发送完毕:这算半个。对于低流量的服务,可不必关心这个事件;这里的发送完毕是指数据写入操作系统缓冲区,将由TCP协议栈负责数据的发送与重传,不代表对方已经接收到数据。
下面我们重点讨论一下消息到达和消息发送完毕事件
消息到达事件
(1)一个socket有2个缓冲区:接收缓冲区,发送缓冲区 (2)socket有数据到来时,数据先被内核接收,存放在内核接收缓冲区中,网络库事件循环中的可读事件被触发,将数据从内核缓冲区移动到应用缓冲区中,并且网络库会回调一个OnMessage函数表示有消息到达。 由于TCP接收到的可能是半包(即数据不完整),OnMessage要根据协议来判断这个数据包是否完整。若不是完整的数据包,OnMessage会立刻返回,直到内核又接收了一些数据,此时网络库中事件循环中的可读事件又触发了,又把数据从内核缓冲区移动到应用层缓冲区中,再次回调OnMessage来判断这个数据包是否完整; 而如果TCP接收到的数据包是完整的,就直接将这个数据包取出来进行处理(read->decode解包->compute->encode打包->write); 接着继续判断,后续的内容是否是一个完整的包,若数据包不完整,则OnMessage立即返回,若数据包完整,则还要继续处理;消息发送完毕事件
(1)假设现在应用层要发送数据,如果内核发送缓冲区足够大,则将要发送的数据全部填入内核缓冲区中,并触发一个发送完成事件,并且网络库会回调一个OnWriteComplete函数表示消息发送完毕;而如果内核发送缓冲区不足以容纳这么多的数据,则只将其中一部分数据填入内核缓冲区,剩余部分追加到应用层的发送缓冲区中,等内核发送缓冲区将数据发送出去后,会触发一个可写事件,在这个事件中就会将应用层发送缓冲区中的数据填充到内核发送缓冲区中,这时如果内核发送缓冲区不足以容纳应用层发送缓冲区中的全部数据,则只将其中一部分数据填入内核缓冲区…就这样直到应用层发送缓冲区中的数据全部填充到内核缓冲区,网络库事件循环中的发送完成事件会被触发,并回调OnWriteComplete表示消息发送完毕。 (2)注意:应用层一定要在应用层发送缓冲区中的数据全部填入内核缓冲区并回调OnWriteComplete表示消息发送完毕后才能继续发送数据,这样做可以避免数据丢包。one loop per thread意思是说每个线程最多只能有一个EventLoop对象。
multiple reactors+threadpool(one loop per thread + threadpool); 每一个reactor都是一个线程;创建了EventLoop对象的线程称为IO线程,其功能是运行事件循环(EventLoop::loop)。
没有创建EventLoop对象的线程就不是IO线程。EventLoop对象构造的时候,会检查当前线程是否已经创建了其他EventLoop对象,如果已创建,终止程序(LOG_FATAL)
EventLoop构造函数会记住本对象所属线程(threadId_)。
eg:25\jmuduo\muduo\net\EventLoop.h
25\jmuduo\muduo\net\EventLoop.cc 25\jmuduo\muduo\net\CMakeLists.txteg测试:25\jmuduo\tests\Reactor_test01.cc
25\jmuduo\tests\Reactor_test02.cc 25\jmuduo\tests\CMakeLists.txt测试:多个线程可以创建EventLoop对象,这些线程都是I/O线程
错误的eg参考:
转载地址:http://tmiws.baihongyu.com/