TCP连接关闭总结
由于涉及面太广,只作简单整理,有兴趣的可参考《UNIX Networking Programming》volum 1, Section 5.7, 5.12, 5.14, 5.15, 6.6 以及7.5 SO_LINGER选项。
以一个简单的echo服务器为例,客户端从标准输入读入字符,发送给服务器,服务器收到后再原样返回,客户端收到后打印到标准输出。
那么,关于套接字的关闭有以下几种情形:
1,客户端关闭连接:
1.1,客户端调用close()
1.2,客户端进程关闭
1.3,客户端调用shutdown()
1.4,客户端调用close()+SO_LINGER选项
1.5,客户端崩溃
2,服务器关闭连接:
2.1,服务器调用close()
2.2,服务器进程关闭
2.3,服务器崩溃
2.4,服务器崩溃+SO_KEEPALIVE选项
============================分割线===============================
1.1与1.2等价,就算客户端进程关闭,系统内核也会自动close(socket),且注意,当socket引用为0时才会真正调用close(),close()总是立即返回的,然后由系统尝试发送完内核缓冲区内的所有数据,接着才发送FIN。
说道这里,不得不谈谈TCP连接关闭的四次握手。可以看成是2组FIN, ACK。主动关闭的一方先发送FIN,收到ACK后,进入FIN_WAIT2状态,此时也叫做“半关闭”状态,特别须要注意的是,此时客户端套接字依然可以接收数据包,但是不能发送数据包。 被动关闭的一方,此时收到FIN了,一般情况下都是由于read(socket)返回0,然后得知对方关闭,close(socket)后,另外一组FIN,ACK随之产生,此时主动方进入TIME_WAIT状态。即四次握手完成。
以上即是正常情况下连接关闭的情形。
再看看1.3,shutdown()与close()主要有3点区别:
shutdown()不理会引用计数与内核缓冲区内剩余待发数据包,直接发送FIN;
shutdown()可以只关闭套接字某个方向的连接,例如关闭发送,关闭接收,或者2者都关闭;
实际上shutdown(write)后,就是上面说的半关闭情形,依然可以完成四次握手。
再看看1.4,为什么要设置SO_LINGER呢
SO_LINGER的目的就是改变close()的默认行为,可以决定close()在哪个状态返回,或者让套接字立即发送RST,从而没有FIN的发送。接收方返回ECONNRESET错误,连接直接关闭。
再来总结下1.1-1.4,这么多关闭连接的方式,那么什么方式才是最好的呢?
择优选择的方式当然是考虑最恶劣的情况,对方主机崩溃或网络故障导致数据包传输停滞。
RST不用考虑了,直接TIME_WAIT状态都没,如果有网络故障,可能下次创建的套接字还会接收到已经被销毁的套接字的数据报。
close()不能保证对方一定收到FIN。
close()+SO_LINGER虽然能控制close()在收到ACK后返回,依然不能保证四次握手完成。
shutdown()先进入半关闭状态,再调用read(),返回0(收到对方FIN)则说明四次握手正常进行,此为最优方式。
其实仔细想想,一般情况也不用这么麻烦,拿网游服务器来说,客户端close()后,就算服务器不知道,那么这种情况归为1.5讨论;如果是服务端close()而客户端不知道,那么归为2.3讨论。总之都有解决办法。。
现在再讨论1.5,很简单,服务端加入链路异常检测机制即可,这也是所有大型TCP服务器必备的机制,定时发送小数据包检测客户端是否有异常退出。
=============================分割线==============================
服务器关闭连接方面:
2.1,2.2等价,一般情况下也与1.1,1.2等价,只是主动关闭方是服务器了。
但是,在我们讨论的例子里,客户端要从标准输入读字符,这是阻塞方式,服务端关闭连接后,客户端无法知道,因为它阻塞在标准输入了,当我们再次输入字符,并发送,收到FIN或RST,此时客户端才关闭。总之,客户端由于某种原因,不能及时调用read(),所以无法得知服务器关闭了连接。
2.3,服务器崩溃,客户端由于一直收不到ACK,会一直尝试发送数据,标准socket大概是9分钟后才会返回错误。
2.3,服务器崩溃,客户端又长时间与服务器没有数据交互,此时设置SO_KEEPALIVE选项可得知。
=============================分割线=============================
后记:网络是门复杂的学问,由此TCP连接的关闭可见一斑。普通程序员通常不会考虑这么细致,但是我相信这些问题一直困扰着他们。
补充说明:经试验,在Windows平台,1.2 2.2情况等同于close()+SO_LINGER选项直接发送RST,可能由于系统必须及时清理资源吧,这点与linux是不同的,有兴趣的可以试试。。
TCP连接关闭总结的更多相关文章
- socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题
Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...
- [转]socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题
Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...
- Linux 内核协议栈之TCP连接关闭
Close行为: 当应用程序在调用close()函数关闭TCP连接时,Linux内核的默认行为是将套接口发送队列里的原有数据(比如之前残留的数据)以及新加入 的数据(比如函数close()产生的FIN ...
- TCP 连接关闭及TIME_WAIT探究
这里主要记录一下TCP连接在关闭的时刻,有哪些细节问题.方便在以后的程序设计中能够注意这些细节, 以避免出现这些错误.首先我们来看一下TCP的状态转换图.如<unix网络编程>卷一所示如下 ...
- TCP连接性能指标之TCP关闭过程(四次挥手)
TCP关闭过程(四次挥手): ESTABLISHED: 当前建立连接状态 CLOSE_WAIT:Server端收到来自Client端的FIN包后,发送ACK回Client端,进入CLOSE_WAIT ...
- 我为 Netty 贡献源码 | 且看 Netty 如何应对 TCP 连接的正常关闭,异常关闭,半关闭场景
欢迎关注公众号:bin的技术小屋,本文图片加载不出来的话可查看公众号原文 本系列Netty源码解析文章基于 4.1.56.Final版本 写在前面..... 本文是笔者肉眼盯 Bug 系列的第三弹,前 ...
- TCP连接——爱的传声筒
TCP连接——爱的传声筒 TCP通信最重要的特征是:有序(ordering)和可靠(reliable).有序是通过将文本流分段并编号实现的.可靠是通过ACK回复和重复发送(retransmission ...
- 关于Kafka producer管理TCP连接的讨论
在Kafka中,TCP连接的管理交由底层的Selector类(org.apache.kafka.common.network)来维护.Selector类定义了很多数据结构,其中最核心的当属java.n ...
- mysql服务器,大量tcp连接状态TIME_WAIT
今天早上,java应用中发现too many open files,检查了下使用的连接数发现基本上在两三百左右,mysql打开的文件数也就几百左右,再看所有tcp连接,发现3306的连接有4000多, ...
随机推荐
- Kali软件库认识
对kali上的软件进行一个初步的认识 信息收集 dmitry -o 将输出保存到%host.txt或由-o文件指定的文件 -i 对主机的IP地址执行whois查找 -w 对主机的域名执行whois查找 ...
- Spring的核心容器
Spring框架的主要功能是通过其核心容器来实现的.Spring提供了2种核心容器:BeanFactory.ApplicationContext. BeanFactory BeanFactory是一个 ...
- MySQL NULL--三值逻辑(Three Value Logic)
三值逻辑(Three Value Logic) 在关系型数据库中,由于NULL值的存在,导致逻辑表达式存在三种值:TRUE/FALSE/UNKNOW. SELECT '=NULL AS C1, ' A ...
- 基于TCP协议的远程终端控制并发socketserver实现以及粘包问题处理
# 客户端 # -*- coding: utf-8 -*- import socketserver import struct import json import subprocess class ...
- VS2005编译QT4.8.2
为什么要编译? 因为安装安装版的QT4.8.2,vs2005编译报错. 1.下载QT4.8.2,qt-everywhere-opensource-src-4.8.2.zip,下载vs-AddIn1.1 ...
- Beta之前-凡事预则立(校园帮-追光的人)
所属课程 软件工程1916 作业要求 Beta之前-凡事预则立 团队名称 追光的人 作业目标 在Beta冲刺之前,提前做好准备和规划 议题 1.讨论组长是否重选的议题和结论. 2.下一阶段需要改进完善 ...
- SpringBoot集成MyBatis的Bean配置方式
SpringBoot集成MyBatis的Bean配置方式 SpringBoot是一款轻量级开发的框架,简化了很多原先的xml文件配置方式,接下来就介绍一下如何不适用XML来配置Mybatis spri ...
- MSc in Robotics
MSc in RoboticsProgramming Methods for Robotics AssignmentIrene Moulitsas & Peter SherarCranfiel ...
- UVA 13024: Saint John Festival(凸包+二分 ,判定多个点在凸包内)
题意:给定N个点,Q次询问,问当前点知否在N个点组成的凸包内. 思路:由于是凸包,我们可以利用二分求解. 二分思路1:求得上凸包和下凸包,那么两次二分,如果点在对应上凸包的下面,对应下凸包的上面,那么 ...
- SparkSQL读写外部数据源--csv文件的读写
object CSVFileTest { def main(args: Array[String]): Unit = { val spark = SparkSession .builder() .ap ...