网络编程的一些错误总结

最近自己在写一套服务器框架,期间遇到很多问题,对于Linux或者windows出错情况下可以通过错误码获取错误信息。为了测试服务器性能,我在客户端开了2000个线程,这样每个线程都创建socket和服务器通信,连接15个线程,再后来的客户端线程connect过程中会失败,我另起了一个客户端进程进行连接,还是能连接15个过后才出现问题,初步可以排除服务器并没有达到连接上限,之后在linux上打印该错误码为111,查询意思为服务器拒绝客户端连接。查询相关资料是监听队列设置为5,只能接受一部分剩余的由于监听队列满了就被拒绝了。之后查询libevent和redis库的一些监听队列大小,设置为128较为合适,这次同样会出现一部分客户端连接失败,因为监听队列总是有限的,尽管如此,极限的情况下一秒同时连接500多个客户端还是没问题。

这个监听队列的知识可以介绍下:
https://cdn.llfc.club/neterror1.gif
这个图说明tcp是三次握手处理连接和四次握手处理断开。

listen函数将主动套接字转换为被动监控套接字,其第二个参数backlog决定了内核的连接缓存队列长度。对于一个给定的监听套接字,内核维护两个队列:

① 未就绪队列,存放没有完成三路握手的连接,监听套接字收到SYN并返回ACK+SYN,连接处于SYN_RECV状态,等待对端发送ACK。如果已完成队列非满,则接收ACK,连接握手完成,进入已完成队列;如果已完成队列满则丢弃ACK,对端重发ACK(对端看到的连接是ESTABLISED状态),若未就绪队列中的SYN_RECV等待直到超时还没进入已完成队列则丢弃连接(对端不知道,只有在读写套接字时才知道)。

② 已完成队列,存放已经完成三路握手的连接(ESTABLISHED),等待accept取走连接。

backlog决定了两个队列的长度之和(并不是说两个队列之和等于backlog,而是存在个转换,依赖于具体实现)。

如果未就绪队列满则忽略新到来的SYN请求,对端重发,如果一直不能进入未就绪队列则对端connect失败返回。

除此之外,由于每个客户端进程我开辟了2000个线程,也会报错errorno为9,意为bad file discirp,错误的文件描述符。

因为linux限制每个进程最多开辟1024个线程。

这些都是实际开发中遇到的一些问题,总结出来以便更好地处理以后的问题。