1、程序初始化
创建监听socket
调用bind函数绑定ip地址、port端口号
调用listen函数监听
调用epoll_create函数创建epollfd
调用epoll_ctrl函数将listenfd绑定到epollfd上,监测listenfd的读事件
在一个无限循环中,调用epoll_wait函数等待事件发生
2、处理客户端请求
1、客户端连接
操作系统检测到监听fd上有读事件,导致epoll_wait从阻塞状态返回,上报监听fd上读事件,
调用accept函数接受连接,返回与客户端对应的的clientfd,将clientfd设置为非阻塞,调用epoll_ctrl将clientfd绑定到epollfd上,绑定时设置监听clientfd的读事件,此时还不能监听该clientfd的写事件。
2、客户端给服务器发数据
epoll_wait函数返回,并表明该clientfd上有读事件,调用recv函数接收数据,
若recv返回0,说明对端关闭了连接,调用epoll_ctrl将clientfd从epollfd上卸载,并关闭该clientfd;
若recv返回大于0,说明收到了数据,将数据存起来,根据协议格式解包。如果是LT模式,则可以调用任意次recv收数据,如果是ET模式,必须一直调用recv直到数据收完,收完标志(recv返回-1,并且错误码为EWOULDBLOCK)
3、服务器给客户端发数据
一般直接调用send发数据,如果数据太大或tcp窗口太小数据发不出去(send返回-1,错误码是EWOULDBLOCK,需要判断是否有剩余数据),调用epoll_ctrl将clientfd绑定到epollfd上,监听该clientfd写事件,如果epoll_wait返回了并告诉clientfd上有写事件,继续发数据,如果数据还是发送不完,继续等待下一次写事件,一旦数据全部发完,移除epoll上该clientfd的写事件监听。
学习链接:https://github.com/0voice