1.poll函数
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd{
int fd;
short events;
short revents;
};
1.1 poll使用基本流程
- 使用signal(SIGPIPE, SIG_IGN)详解
如果客户端关闭套接字,而服务器端调用了一次write,服务器会接收到一个RST segment(TCP 传输层);如果服务器端再次调用了write,这个时候就会产生SIGPIPE信号。 - TIME_WAIT状态对大并发服务器的影响
应尽可能在服务器端避免出现TIME_WAIT状态。
如果服务器端主动断开连接,即先于客户端调用close函数,服务端就会进入TIME_WAIT状态,占用内核资源,会影响到并发。
在协议设计上应该让客户端主动断开连接,这样就把TIME_WAIT状态分散到大量的客户端。
如果客户端不活跃了,一些客户端不断开连接,这样子就会占用服务器端的连接资源,所以服务端也要有个机制来踢掉不活跃的连接。 - read可能并没有把connfd所对应的接收缓冲区的数据读完(一个数据包,两次read才能读完)
这种情况下connfd仍然是活跃的,我们应该将读到的数据保存在connfd应用层缓冲区。 - write发送的时候,内核的发送缓冲区满了
这种情况下也应该有一个应用层的发送缓冲区
POLLOUT触发事件:内核缓冲区不满,可以容纳数据 - accept返回EMFILE处理方法(进程打开的文件描述符达到上限了)
- 调高进程文件描述符数目
- 死等,等到其它文件关闭
- 退出程序,不符合服务器7*24小时工作,高可用
- 关闭监听套接字,那什么时候重新打开
- 如果是epoll模型,可以改用边沿触发,问题是如果漏掉了一次accept,程序再也不会收到新连接
- 准备一个空闲的文件描述符。遇到这种情况,先关闭这个空闲的文件,获得一个文件描述符名额,再accept拿到socket连接的文件描述符,随后立刻close掉,这样就优雅地断开了客户端的连接,最后重新打开空闲文件,把“坑”天上,以备再次出现这种情况时使用。
1.2 编码实现C/S回射客户服务器