四次挥手与Socket API

尾调露台
• 阅读 3132

在《三次握手与Socket API》中我们详细讲解了三次握手以及与之相关的API,三次握手是TCP协议的初始阶段,用来建立双方通信连接,显然有建立连接就有断开连接,那么TCP是如何断开连接的呢?

奇怪的四次挥手

TCP协议建立连接需要进行三次信息交互,断开连接时却需要四次信息交互,这四次信息交互被形象的称为四次挥手,那么TCP在断开连接时为什么需要奇怪的四次挥手而不是三次挥手呢?要想回答这个问题我们必须对TCP协议有进一步的理解。

话多的人与话少的人

生活中总会有这两类人,一类话多,一类话少,话少的那个言简意赅很快就无话可说了,话多的那个滔滔不绝没完没了,因此就会有这样的情形:

A: 今天天气这不错啊
A: 今天饭也好吃
A: 是吧
                   是的 :B
                我说完了 :B
A: 我还没说完呢
A: 明天就周五啦
A: 开心
A: blablabla
A: 我也说完了

当这两类人在聊天时就会出现B说完但A没说完的情况,这时B不再说话但是可以继续听A说,当A也说完后整个聊天过程才算结束。

TCP通信过程和人聊天又有多大区别呢?

有话多话少的人当然也会有数据多数据少的客户端以及服务器。

为什么要四次挥手:半关闭

在TCP通信中一方表示“我说完了”实际上是通过向对方发送一条带有FIN标识的消息来实现的,当一方收到FIN信息时就知道接下来对方就不会再发送数据了,这在TCP协议中被称为半关闭,half-close。

TCP为什么要支持半关闭呢?为什么不是一方说完大家都闭嘴呢?

原来TCP通信和两个人聊天是一样的,你在说话的同时也在听,也就是说你可以同时收发信息,这就是所谓的全双工通信,在这种通信方式下你说完了不代表对方也说完了,因此只有双方都说完了连接才能完全关闭。

TCP也是全双工通信,TCP规定通信的任意一方都可以向对方发送FIN信息(表示我说完了),但这也仅仅表示一方没什么要发送的了,但这并不影响对方继续发送数据(对方还没发送完数据)。

这就是为什么TCP支持半关闭的原因,半关闭的本质就是TCP通信中一方已经没什么数据要发送了,虽然没有数据要发送但还可以继续接收数据

四次挥手的过程

理解了前几节接下来就简单啦,假设有一个话少的客户端和一个话多的服务器端就会有如下情形:
四次挥手与Socket API
从图中我们可以看出虽然客户端发送了FIN信息但此时服务器端还有数据要发送,因此服务器端没有理会客户端发送的FIN而是继续发送数据直到服务器端也发送完,此时服务器端发送FIN表示数据发送完毕,客户端接收到消息后进行ACK回复,这时TCP连接才真正断开。

不过值得注意的是,作为程序员在网络编程中我们几乎不会遇到上述情形,通常客户端向服务器端发送FIN后服务器端就不会再向客户端继续发送数据了,一般情况下TCP通信的整个过程都是客户端来主导的,客户端主动发起连接,获取到想要的信息后主动断开连接,服务器端只是被动同客户端建立链接,客户端想要什么服务器端经过处理后就返回给客户端什么,当客户端不想再聊天时服务器端也不会还在滔滔不绝,总而言之,客户端与服务器就好比用户和客服一样,整个过程都是用户来主导的,客服只是被动的来回答问题,当用户没什么问题后没有哪个客服还会继续和用户聊下去,当然客服让用户给好评除外,放心,服务器端是不需要客户端给好评的 :) ,因此我们通常看到的这样的情形:
四次挥手与Socket API
有的同学可能会想,为什么B发送的ACK和FIN不能和三次握手一样合并成一次呢?就像这样:
四次挥手与Socket API
如果只有三次挥手那么TCP就没有办法支持半关闭了,三次挥手实际是在说“如果有一方闭嘴那么我们都闭嘴”,虽然作为程序员我们在网络编程时遇到的都是这种情形,但是从TCP协议层面来说应该支持半关闭,也就是支持通信双方中一个话多一个话少的情形。

现在你应该明白为什么要四次挥手而不能是简单的三次了吧。
四次挥手与close
和三次握手一样,四次挥手也有与之相对应的API,这样的API有两个,一个是我们常用的close,另一个是shutdown。

close是我们最常使用的一个,既然close是最常用的,那么close也就用在“一方闭嘴大家都闭嘴”的情形,如图所示:
四次挥手与Socket API

我们已经知道四次挥手通常是由客户端来发起的,当客户端执行close函数后会向服务器端发出FIN消息,服务器端操作系统接收到该信息后向服务器进程发出EOF(end of file),这时服务器无论调用send还是recv都会失败,此时服务器端认为客户端已经关闭了连接,因此调用close函数关闭同客户端的连接,当客户端接收到FIN信息后进行ACK回复确认,整个四次挥手的过程完毕。

四次挥手与shutdown:半关闭
客户端和服务器使用close来完成四次挥手是最常见的过程,即“一方闭嘴大家都闭嘴”,我们知道作为全双工通信协议的TCP还需要支持半关闭,也就是说一方说完但另一方还在说的场景,这时先说完的就只能听了,作为程序员我们需要知道几乎没有什么应用场景要用到TCP提供的半关闭能力。

当客户端调用close后如果服务器端没有理会而是继续向客户端发数据,那么此时客户端是接收不到的,当然这就是客户端调用close函数的目的。

而如果客户端表示:“我没什么要说的了,所以要向服务器发送FIN,但是我还想听服务器啰嗦一会儿直到对方也说完”该怎么办呢?这时客户端就不能调用close了而是应该调用socket提供的另一个API,也就是shutdown,典型的场景如图所示:
四次挥手与Socket API

虽然客户端调用shutdown向服务器端发送了FIN表示自己说完了,但是服务器端还是可以继续向客户端发送任意多的数据,而客户端依然可以接收到数据,直到服务器端也发送FIN消息客户端回复ACK确认后连接才算是真正关闭。

现在你应该明白如何使用shutdown利用TCP的半关闭能力了吧。

总结

本文是继《三次握手与Socket API》的第二篇,讲述了四次挥手的过程以及为什么需要四次挥手,之所以需要四次挥手是因为TCP协议需要提供一种被称为半关闭的能力,但是很少有应用场景需要依赖该能力。作为程序员我们需要知道大部分情况下使用close就可以完成四次挥手,但是如果需要依赖TCP提供的半关闭能力那么需要使用另一个API,也就是shutdown。

如果你喜欢这一系列的文章,也欢迎关注我的微信公共账号,码农的荒岛求生,获取更多内容。

四次挥手与Socket API

计算机内功决定程序员职业生涯高度
点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
tcp编程、socket编程、redis
tcp编程(需要建立连接,三次握手,四次挥手,然后发送信息流,数据包是有序的)udp编程(知道IP、端口直接发送数据,数据包可能是无序的)1、客户端和服务器客!(http
xiguaapp xiguaapp
4年前
tcp的三次握手四次挥手
tcp的三次握手流程:在tcp/ip协议中,tcp协议提供可靠的连接服务,采用三次握手建立一个连接。第一次握手:建立连接时,客户端发送SYN包【synj】到服务器,并进入SYN_SEND状态,等待服务器确认;第二次握手:服务器收到SYN包,必须确认客户的SYN(ackj1),同时自己也发送一个SYN包(syn
捉虫大师 捉虫大师
3年前
4个实验,彻底搞懂TCP连接的断开
前言看到这个标题你可能会说,TCP连接的建立与断开,这个我熟,不就是三次握手与四次挥手嘛。且慢,脑海中可以先尝试回答这几个问题:四次挥手是谁发起的?如果断电/断网了连接会断开吗?什么情况下没有四次挥手连接也会断开?这不是面试,而是遇到了实际问题,至于是什么问题,容我先卖个关子,本文也不会解答,后面会有一篇专门的文章来说遇到的问题是啥,所以在讲实际问题
Wesley13 Wesley13
3年前
TCP的三次握手与四次挥手
TCP的三次握手与四次挥手一、TCP(TransmissionControlProtocol传输控制协议)TCP是面向对连接,可靠的进程到进程通信的协议TCP是提供全双工服务,即数据可在同一时间双向传输二、TCP报文段(封装在IP数据报
Wesley13 Wesley13
3年前
TCP三次握手和四次挥手
建立TCP连接:三次握手TCP在传输数据之前,首先需要建立好TCP连接,后续所有数据都基于这个已建立的连接来传输,建立TCP连接的过程通常被描述为三次握手屏幕快照2020072716.44.59!TCP三次握手和四次挥手(https://s4.51cto.com/images/blog/202007/27/e095cdb6ee5e99
Easter79 Easter79
3年前
TCP三次握手与Linux的TCP内核参数优化
感谢各位技术大佬的资料分享,这里我把我理解的内容做一个整理一:TCP的三次握手1、TCP简述  TCP是一个面向连接的协议,在连接双方发送数据之前,首先需要建立一条连接。TCP建立连接可以简单称为:三次握手(说白了就是建立一个TCP连接的时候,客户端
Wesley13 Wesley13
3年前
TCP连接过程及报文解析
可能大家都听过TCP建立连接时需要经历三次握手和四次挥手的。那么具体的握手挥手的过程是怎么样的呢?这篇文章就通过WireShark抓包来了解TCP连接建立和断开的过程。实验方法:写一段简单的代码代码客户端和服务端,分别部署,让客户端主动像服务器发起连接,随后断开。让WireShark抓股这个过程中产生了哪些包,并对其分析。(注:Wire
Wesley13 Wesley13
3年前
TCP是如何实现三次握手的?
什么是三次握手1.TCP是网络传输层的协议,提供面向连接的可靠的字节流服务,要通信得先建立连接2.所谓三次握手就是指,建立一个TCP连接时,需要CLient与Server发送三个包,确认连接的建立3.这一过程由Client执行connect触发简单描述下三次握手的具体过程第一
Wesley13 Wesley13
3年前
Go语言 之TCP三次握手
所谓三次握手(ThreeWayHandshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。好比两个人在打电话:Client:“喂,你听得到吗?”Server:“我听得到,你听得到我吗?”Client:“我能听到你,今天balabala…”建立连接(三次握手)的过程:1.客户端
Wesley13 Wesley13
3年前
TCP三次握手和四次挥手
TCP建立连接为什么是三次握手,而不是两次或四次?TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6。顺便说一句,原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要。举个日常例子,打电话时我们对话如下:对应为客户端与服务器之间的通信:!(https://oscimg.oschina.net/oscnet
Mebius Mebius
2年前
什么是代理ip?代理ip的用途有哪些?该如何获取代理ip?
我们在网页中输入网址后发生了什么呢?1.浏览器获取域名2.通过DNS协议获取域名对应服务器的ip地址3.浏览器和对应的服务器通过三次握手建立TCP连接4.浏览器通过HTTP协议向服务器发送数据请求5.服务器将查询结果返回给浏览器6.四次挥手释放TCP连接7