首页 > 代码库 > TCP_DEFER_ACCEPT的坑
TCP_DEFER_ACCEPT的坑
我实现了一个server,支持HTTP协议和内部私有协议,为了简化部署,我设计成一个端口同时兼容两种协议的客户端。根据连接后到达的消息头自动识别客户端协议。这种事情的传统做法是,accept后加入epoll,当fd第一次可读时,读出一些并解析,判断协议类型。
创建相应的上下文对象,开始服务。这样就引入了中间状态,为了省事,我用了TCP_DEFER_ACCEPT来简化这个过程。
TCP_DEFER_ACCEPT,是Linux下的socket支持一个tcp选项,man这么说的:
TCP_DEFER_ACCEPT
Allows a listener to be awakened only when data arrives on the socket. Takes an integer value (seconds), this can bound the maximum number of
attempts TCP will make to complete the connection. This option should not be used in code intended to be portable.
这样,当accept后,马上就读出并解析协议头,然后再把fd设置为非阻塞的,创建上下文对象,代码简化了不少。
但是今天用大量短连接压测时,发现连接数过了几千后,程序急剧变慢,最后干脆停止响应了。gdb上去看发现居然阻塞在recv的地方,加时间日志发现,recv居然有不少耗时数百毫秒,而如果先设置成非阻塞的,读取时就会大量返回EAGAIN错误。看来行为和文档并不一样。
最后,我把代码改为在epoll通知可读时再读取并解析,故障消失。
TCP_DEFER_ACCEPT的坑