梳理一下程序的大概流程,主要是为了熟悉网络编程。
1. 非阻塞的套接字与epoll
又对epoll有了一定的了解,参考连接 。
ET(边缘触发模式),也就是对套接字的可读可写这些事件,只会相应一次,相应结束之后,需要再次重新注册事件,才会触发。所以代码里会频繁的对套接字进行mod修改操作:
并且,对于非阻塞的 socket,此时 send 函数返回 -1,错误码为 EAGAIN 或 EWOULDBLOCK,你一定要继续注册检测可写事件,否则你剩余的数据就再也没有机会发送了,因为 ET 模式的可写事件再也不会触发。
关于LT和ET的总结:
- LT 模式下,读事件触发后,可以按需收取想要的字节数,不用把本次接收到的数据收取干净(即不用循环到 recv 或者 read 函数返回 -1,错误码为 EWOULDBLOCK 或 EAGAIN);ET 模式下,读事件必须把数据收取干净,因为你不一定有下一次机会再收取数据了,即使有机会,也可能存在上次没读完的数据没有及时处理,造成客户端响应延迟。
- LT 模式下,不需要写事件一定要及时移除,避免不必要的触发浪费 CPU 资源;ET 模式下,写事件触发后,如果还需要下一次的写事件触发来驱动任务(例如发上次剩余的数据),你需要继续注册一次检测可写事件。
2. 回调函数
设想一个场景,类A中有一个类B的成员。但是此时需要在类B中调用类A的成员函数,该怎么办?
- 类B中没有类A的成员,因此无法直接调用
- 用指针?在类B中传递进一个类A的指针。此处需要设置智能指针,防止循环引用,较麻烦
- 可以使用回调函数,利用function 和bind 设置回调函数。