《Linux高性能服务器编程》——3.5 复位报文段

简介: 本节书摘来自华章计算机《Linux高性能服务器编程》一书中的第3章,第3.5节,作者 游双,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.5 复位报文段

在某些特殊条件下,TCP连接的一端会向另一端发送携带RST标志的报文段,即复位报文段,以通知对方关闭连接或重新建立连接。本节讨论产生复位报文段的3种情况。

3.5.1 访问不存在的端口

3.4.1小节提到,当客户端程序访问一个不存在的端口时,目标主机将给它发送一个复位报文段。考虑从Kongming20上执行telnet命令登录ernest-laptop上一个不存在的54321端口,并用tcpdump抓取该过程中两台主机交换的TCP报文段。具体操作过程如下:

$ sudo tcpdump -nt -i eth0 port 54321    #仅抓取发送至和来自54321端口的TCP报文段
$ telnet 192.168.1.108 54321
Trying 192.168.1.108...
telnet: connect to address 192.168.1.108: Connection refused

telnet程序的输出显示连接被拒绝了,因为这个端口不存在。tcpdump抓取到的TCP报文段内容如下:

1. IP 192.168.1.109.42001 > 192.168.1.108.54321: Flags [S], seq 21621375, win
   14600, length 0
2. IP 192.168.1.108.54321 > 192.168.1.109.42001: Flags [R.], seq 0, ack 
   21621376, win 0, length 0

由此可见,ernest-laptop针对Kongming20的连接请求(同步报文段)回应了一个复位报文段(tcpdump输出R标志)。因为复位报文段的接收通告窗口大小为0,所以可以预见:收到复位报文段的一端应该关闭连接或者重新连接,而不能回应这个复位报文段。

实际上,当客户端程序向服务器的某个端口发起连接,而该端口仍被处于TIME_WAIT状态的连接所占用时,客户端程序也将收到复位报文段。

3.5.2 异常终止连接

前面讨论的连接终止方式都是正常的终止方式:数据交换完成之后,一方给另一方发送结束报文段。TCP提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有排队等待发送的数据都将被丢弃。

应用程序可以使用socket选项SO_LINGER来发送复位报文段,以异常终止一个连接。我们将在第5章讨论SO_LINGER选项。

3.5.3 处理半打开连接

考虑下面的情况:服务器(或客户端)关闭或者异常终止了连接,而对方没有接收到结束报文段(比如发生了网络故障),此时,客户端(或服务器)还维持着原来的连接,而服务器(或客户端)即使重启,也已经没有该连接的任何信息了。我们将这种状态称为半打开状态,处于这种状态的连接称为半打开连接。如果客户端(或服务器)往处于半打开状态的连接写入数据,则对方将回应一个复位报文段。

举例来说,我们在Kongming20上使用nc命令模拟一个服务器程序,使之监听12345端口,然后从ernest-laptop运行telnet命令登录到该端口上,接着拔掉ernest-laptop的网线,并在Kongming20上中断服务器程序。显然,此时ernest-laptop上运行的telnet客户端程序维持着一个半打开连接。然后接上ernest-laptop的网线,并从客户端程序往半打开连接写入1字节的数据“a”。同时,运行tcpdump程序抓取整个过程中telnet客户端和nc服务器交换的TCP报文段。具体操作过程如下:

$ nc –l 12345                #在Kongming20上运行服务器程序
$ sudo tcpdump –nt –i eth0 port 12345
$ telnet 192.168.1.109 12345        #在ernest-laptop上运行客户端程序
Trying 192.168.1.109...
Connected to 192.168.1.109.
Escape character is '^]'.            #此时断开ernest-laptop的网线,并重启服务器
a(回车)                    #向半打开连接输入字符a
Connection closed by foreign host.

telnet的输出显示,连接被服务器关闭了。tcpdump抓取到的TCP报文段内容如下:

1. IP 192.168.1.108.55100 > 192.168.1.109.12345: Flags [S], seq 3093809365, 
   length 0
2. IP 192.168.1.109.12345 > 192.168.1.108.55100: Flags [S.], seq 1495337791, 
   ack 3093809366, length 0
3. IP 192.168.1.108.55100 > 192.168.1.109.12345: Flags [.], ack 1, length 0
4. IP 192.168.1.108.55100 > 192.168.1.109.12345: Flags [P.], seq 1:4, ack 1, 
   length 3
5. IP 192.168.1.109.12345 > 192.168.1.108.55100: Flags [R], seq 1495337792, 
   length 0

该输出内容中,前3个TCP报文段是正常建立TCP连接的3次握手的过程。第4个TCP报文段由客户端发送给服务器,它携带了3字节的应用程序数据,这3字节依次是:字母“a”、回车符“r”和换行符“n”。不过因为服务器程序已经被中断,所以Kongming20对客户端发送的数据回应了一个复位报文段5。

相关文章
|
4月前
|
消息中间件 存储 缓存
【嵌入式软件工程师面经】Linux系统编程(线程进程)
【嵌入式软件工程师面经】Linux系统编程(线程进程)
117 1
|
25天前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
25天前
|
Shell Linux
Linux shell编程学习笔记82:w命令——一览无余
Linux shell编程学习笔记82:w命令——一览无余
|
1月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
52 6
|
1月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
89 3
|
29天前
|
Shell Linux Python
python执行linux系统命令的几种方法(python3经典编程案例)
文章介绍了多种使用Python执行Linux系统命令的方法,包括使用os模块的不同函数以及subprocess模块来调用shell命令并处理其输出。
18 0
|
2月前
|
项目管理 敏捷开发 开发框架
敏捷与瀑布的对决:解析Xamarin项目管理中如何运用敏捷方法提升开发效率并应对市场变化
【8月更文挑战第31天】在数字化时代,项目管理对软件开发至关重要,尤其是在跨平台框架 Xamarin 中。本文《Xamarin 项目管理:敏捷方法的应用》通过对比传统瀑布方法与敏捷方法,揭示敏捷在 Xamarin 项目中的优势。瀑布方法按线性顺序推进,适用于需求固定的小型项目;而敏捷方法如 Scrum 则强调迭代和增量开发,更适合需求多变、竞争激烈的环境。通过详细分析两种方法在 Xamarin 项目中的实际应用,本文展示了敏捷方法如何提高灵活性、适应性和开发效率,使其成为 Xamarin 项目成功的利器。
46 1
|
2月前
|
安全 Linux 开发工具
探索Linux操作系统:从命令行到脚本编程
【8月更文挑战第31天】在这篇文章中,我们将一起潜入Linux操作系统的海洋,从最基础的命令行操作开始,逐步深入到编写实用的脚本。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和实用技能。我们将通过实际代码示例,展示如何在日常工作中利用Linux的强大功能来简化任务和提高效率。准备好了吗?让我们一起开启这段旅程,探索Linux的奥秘吧!
|
2月前
|
Linux
揭秘Linux心脏:那些让你的编程事半功倍的主要系统调用
【8月更文挑战第31天】Linux中的系统调用是操作系统提供给应用程序的接口,用于请求内核服务,如文件操作、进程控制等。本文列举了22种主要系统调用,包括fork()、exec()、exit()、wait()、open()、close()、read()、write()等,并通过示例代码展示了如何使用fork()创建新进程及使用open()、write()、close()操作文件。这些系统调用是Linux中最基本的接口,帮助应用程序与内核交互。
38 1
|
2月前
|
Linux 程序员 开发者
源社区的兴起:从“代码隐士”到Linux引领的“全球编程嘉年华”
在编程的古老森林中,曾有“代码隐士”默默耕耘,惧怕智慧外泄。直到“开源”春风拂过,源社区如全球编程嘉年华盛开!开源文化颠覆了“独门秘籍”的传统,像“武林秘籍共享”般在网络上公开,鼓励知识传播与智慧碰撞。程序员组队开发,分享代码,提升科技实力。Linux则从“首席大厨”变身为“总导演”,以强大内核调制出诱人应用,引领潮流并推动技术创新。加入这场没有血腥厮杀,只有知识盛宴的“编程版《饥饿游戏》”吧!与全球开发者共享编程的乐趣与成就感!别忘了带上你的“独门秘籍”,可能下一个改变世界的创意就在其中!
64 7