TCP Linger的坑

昨天和同事奋战几个小时,解决了一个linger造成的bug。

现象是这样的,这是一个我从原型接手,扩充了各种功能成为可用代码的epoll实现的非阻塞socket server程序,接收大量的短连接,测试发现性能有问题,用gperftools的cpu profiler也没看出问题。就在一些可疑调用的地方前后加时间,耗时较长的就打出来。一开始发现是epoll处理某些fd的时间有时很长,最后发现是close(fd)耗时达一秒。我才想起来,上周为了解决短连接丢数据问题,把原来linger的超时从0改为了1,改回去现象就消失了,最后彻底去掉就解决了。

原来,在linux下,只要开启了linger并设置了非0的超时,那么close时,如果有数据待发送,就会阻塞最多达指定的时间,不管socket是不是阻塞的。看了一下内核代码,也确认是这样处理的,有点出乎意料。

// net/ipv4/tcp.c

void tcp_close(struct sock *sk, long timeout)
{
        // ...
	sk_stream_wait_close(sk, timeout);
        // ...
}
// net/ipv4/af_inet.c

int inet_release(struct socket *sock)
{
	struct sock *sk = sock->sk;

	if (sk) {
		long timeout;
                // ...
		timeout = 0;
		if (sock_flag(sk, SOCK_LINGER) &&
		    !(current->flags & PF_EXITING))
			timeout = sk->sk_lingertime;
		sock->sk = NULL;
		sk->sk_prot->close(sk, timeout);
	}
	return 0;
}

回想当初是这个错误的原因是,因为manpage里没找到,我查一些文章却说close一个这样的socket时,会返回EWOULDBLOCK,大意了。至于代码当初为什么会开启linger,估计是为了消除TIME_WAIT,但是这种做法是得不偿失的。

查阅MSDN closesocket的文档,发现winsock下的行为不一样,会返回EWOULDBLOCK,这可能就是误导我的文章的说法的出处吧。

结论:对于使用非阻塞socket的程序,linger基本就是个无用且有害的选项,开启并设置0超时会丢数据,设置非0超时又会阻塞,因此千万不要用它。

时间: 2025-01-20 05:28:58

TCP Linger的坑的相关文章

【转】网络编程常见问题总结

网络编程常见问题总结 这里对在网络程序中遇到的一些问题进行了总结, 这里主要针对的是我们常用的TCP socket相关的总结, 可能会存在错误, 有任何问题欢迎大家提出. 对于网络编程的更多详细说明建议参考下面的书籍 <UNIX网络编程> <TCP/IP 详解> <Unix环境高级编程> < div> 网络编程常见问题总结 相关说明 非阻塞IO和阻塞IO 基本概念 设置 区别: 读: 写: 超时控制: 长连接和短连接的各种可能的问题及相应的处理 短连接: 长

TCP/IP详解卷二——开坑记

最近我一直在读Gary R. Wright和W. Richard Stevens合著的TCP/IP详解卷二,深感Net/3版本协议栈实现的繁杂.本来打算看完书本,再看下陈硕大大写的基于TUN/TAP虚拟网卡Net/3移植版(他的版本是ip层以及下层实现都由虚拟网卡提供),再自己撸个简化版的用户态协议栈,之后抽空再看看UNIX网络编程卷一(全是api应用,有隐藏的坑),算是对计算机网络基础一个完整的学习(当然,再后面就是阅读各种开源代码).可是,这TCP/IP详解卷二真是够繁杂的,其实繁杂倒也无所

tcp.validnode_checking踩过的坑

对Oracle 检查ip合法性,就必须在服务器端的sqlnet.ora文件中设置如下参数 TCP.INVITED_NODES=(10.0.0.36,10.0.0.1,10.0.0.35) TCP.EXCLUDED_NODES=(10.0.0.2) 启动监听出现如下错误 [[email protected] admin]$ lsnrctl status LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 12-MAR-2018 18:32:1

tcp状态-TIME_WAIT与CLOSE_WAIT带来的坑

tcp状态: http://www.cnblogs.com/DengGao/p/tcp_state.html 1. tcp连接会占用系统资源(文件描述符), 有时候甚至会导致系统假死(不能发起或者处理tcp请求). 2. TIME_WAIT状态tcp过多的原因: TIME_WAIT等待状态,这个状态又叫做2MSL状态,主动关闭方会出现TIME_WAIT.状态说的是在TIME_WAIT2发送了最后一个ACK数据报以后,要进入TIME_WAIT状态,这个状态是防止最后一次握手的数据报没有传送到对方那

socket TCP编程中connect的一些坑

1.服务端listen成功后,系统就自动接收客户端请求了 man listen: 其中有一段 The  behavior of the backlog argument on TCP sockets changed with Linux 2.2.  Now it specifies the  queue  length  for  completely  established sockets  waiting  to  be  accepted, instead of the number o

【服务器踩坑】SSMS链接Ubuntu上的SQL Server 2019 报错 TCP Provider: Error code 0x2746

昨天在一台Ubuntu18.04.2 上安装了SQL Server 2019 for Linux 服务正常启动了,但是却无法通过命令行工具或者远程Windows机器上的SSMS链接. SSMS错误是 Sqlcmd的错误是 Microsoft ODBC Driver 17 for SQL Server : TCP Provider: Error code 0x2746 关闭了防火墙,还是不行. 无奈访问了一下著名的同性交友网站Stackoverflow,其中有个帖子提到了这是由于SSL版本不一致造

Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新Client API的使用要点,高可用性测试,以及各种坑 (转载)

Kafka 0.9版本对java client的api做出了较大调整,本文主要总结了Kafka 0.9在集群搭建.高可用性.新API方面的相关过程和细节,以及本人在安装调试过程中踩出的各种坑. 关于Kafka的结构.功能.特点.适用场景等,网上到处都是,我就不再赘述了,直接进入正文 Kafka 0.9集群安装配置 操作系统:CentOS 6.5 1. 安装Java环境 Zookeeper和Kafka的运行都需要Java环境,所以先安装JRE,Kafka默认使用G1垃圾回收器,如果不更改垃圾回收器

Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新版Java Client的使用要点,高可用性测试,以及各种坑(二)

上一节中(点此传送),我们完成了Kafka集群的搭建,本节中我们将介绍0.9版本中的新API,以及Kafka集群高可用性的测试 1. 使用Kafka的Producer API来完成消息的推送 1) Kafka 0.9.0.1的java client依赖: <dependency>     <groupId>org.apache.kafka</groupId>     <artifactId>kafka-clients</artifactId>  

TCP随笔

目录 前言 正文 time_wait和rst fin与连接关闭 nagel和ack延迟算法 滑动窗口与拥塞控制 文末 总结 测试代码 前言 网上已经有大量关于tcp的文章,感觉作为一名技术人员,不写一篇tcp相关的文章,对职业生涯来说是一种遗憾,但是又不想单纯造一篇轮子,带着这种矛盾的心态,一拖再拖,最后还是造了一篇轮子.本文不适合完全的小白,适合有一定开发经验的初级开发. 文中一,二两节主要对rst(异常情况)及fin(关闭信号)及相关的一些socket操作,以及各种情况时,调用相关的函数会得