文档章节

Linux网络编程——浅谈 TCP 三次握手和四次挥手

Zero零_度
 Zero零_度
发布于 2017/05/24 08:50
字数 1812
阅读 13
收藏 0

一、tcp协议格式

 

 

 

二、三次握手

 

在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,采用三次握手建立一个连接。

 

 

第一次握手:建立连接时,客户端发送 syn 包(tcp协议中syn位置1,序号为J)到服务器,并进入 SYN_SEND 状态,等待服务器确认; 

 

第二次握手:服务器收到 syn 包,必须确认客户的 SYN,同时自己也发送一个 SYN 包,即 SYN+ACK包(tcp协议中syn位置1,ack位置1,序号K,确定序号为J+1),此时服务器进入 SYN_RECV 状态; 

 

第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(tcp协议中ack位置1,确认序号K+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。

 

 

 

通过这样的三次握手,客户端与服务端建立起可靠的双工的连接,开始传送数据。 三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?

 

我们举一个现实生活中两个人进行语言沟通的例子来模拟三次握手

 

第一次对话: 

老婆让甲出去打酱油,半路碰到一个朋友乙,甲问了一句:哥们你吃饭了么? 

 

结果乙带着耳机听歌呢,根本没听到,没反应。甲心里想:跟你说话也没个音,不跟你说了,沟通失败。说明乙接受不到甲传过来的信息的情况下沟通肯定是失败的。

 

如果乙听到了甲说的话,那么第一次对话成功,接下来进行第二次对话。 


 

第二次对话: 

乙听到了甲说的话,但是他是老外,中文不好,不知道甲说的啥意思也不知道怎样回答,于是随便回答了一句学过的中文 :我去厕所了。甲一听立刻笑喷了,“去厕所吃饭”?道不同不相为谋,离你远点吧,沟通失败。说明乙无法做出正确应答的情况下沟通失败。 

 

如果乙听到了甲的话,做出了正确的应答,并且还进行了反问:我吃饭了,你呢?那么第二次握手成功。 

 

通过前两次对话证明了乙能够听懂甲说的话,并且能做出正确的应答。接下来进行第三次对话。 

 

 

第三次对话: 

甲刚和乙打了个招呼,突然老婆喊他,“你个死鬼,打个酱油咋这么半天,看我回家咋收拾你”,甲是个妻管严,听完吓得二话不说就跑回家了,把乙自己晾那了。乙心想:这什么人啊,得,我也回家吧,沟通失败。说明甲无法做出应答的情况下沟通失败。 

 

如果甲也做出了正确的应答:我也吃了。那么第三次对话成功,两人已经建立起了顺畅的沟通渠道,接下来开始持续的聊天。 

 

通过第二次和第三次的对话证明了甲能够听懂乙说的话,并且能做出正确的应答。 可见,两个人进行有效的语言沟通,这三次对话的过程是必须的。

 

同理对于TCP为什么需要进行三次握手我们可以一样的理解: 

为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。 

 

三、四次挥手

由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这好比,我们打电话(全双工),正常的情况下(出于礼貌),通话的双方都要说再见后才能挂电话,保证通信双方都把话说完了才挂电话

 

TCP 的四次握手是为了保证通信双方都关闭了连接,具体过程如下:

 

 

1)客户端 A 在应用层调用close时会激发底层发送一个 FIN(tcp协议中FIN位置1、序号为M,结合上图分析)请求,用来关闭客户 A 到服务器 B 的数据传送,客户端A此时处于半关闭状态(应用层无法接收数据但底层还可以接收数据);

 

2)服务器 B 底层收到客户端A的FIN时会做两件事

2.1)第1件事:收到客户端A的FIN时底层会主动回发一个ACK(tcp协议中ACK位置1,确认序号M+1)

2.2)第2件事:收到客户端A的FIN时,导致服务器B的应用层read()返回0(告诉服务器B应用层:客户端A关闭了)

 

3)服务器B应用层调用close()激发底层给客户端 A 发送一个 FIN(tcp协议中FIN位置1、序号为N),这是服务器B已处于半关闭状态;

 

4)客户端 A 底层回发 ACK(tcp协议中ACK位置1,确认序号N+1) 给服务器B,这是客户端A、服务器B都处于完全关闭状态,回收相应的资源。

 

 

 

为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

 

这是因为服务端的 LISTEN 状态下的 SOCKET 当收到 SYN 报文的建连请求后,它可以把 ACK 和 SYN(ACK 起应答作用,而 SYN 起同步作用)放在一个报文里来发送。但关闭连接时,当收到FIN 报文通知时,如果能将ACK、FIN放在一个报文里那么就有了三次挥手,但是这是不可能,因为ACK是服务器B一收到FIN报文底层就回发的,而服务器B的FIN是应用层调用close()激发的,所以它这里的 ACK 报文和 FIN 报文在发送的时间上都是分开的,不可能同时发送。

 

为什么 TIME_WAIT 状态还需要等 2MS L后才能返回到 CLOSED 状态?

 

这是因为虽然双方都同意关闭连接了,而且握手的 4 个报文也都协调和发送完毕,按理可以直接回到 CLOSED 状态(就好比从 SYN_SEND 状态到 ESTABLISH 状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的 ACK 报文会一定被对方收到,因此对方处于 LAST_ACK 状态下的 SOCKET 可能会因为超时未收到 ACK 报文,而重发 FIN 报文,所以这个 TIME_WAIT 状态的作用就是用来重发可能丢失的 ACK 报文。(里面涉及的状态是什么意思,详情请看《TCP 通信过程中各步骤的状态》

本文转载自:http://blog.csdn.net/lianghe_work/article/details/46458889

Zero零_度
粉丝 69
博文 1258
码字总数 257684
作品 0
程序员
私信 提问
TCP三次握手和四次挥手

哈喽!大家好,今天我们来共同认识一下什么是三次握手和四次挥手,来了解一下TCP客户端和服务器之间是如何进行通信的,又如何释放连接的呢? 其实,实际上三次握手就是指建立一个TCP连接时,...

MRUJ
2017/09/01
0
0
【转】跟着动画来学习TCP三次握手和四次挥手

最近看到一篇很通俗易懂的描述TCP三次握手和四次挥手概念的文章,觉得特别好,怕以后找不到了,特意转载在这里学习一下。 原文地址:跟着动画来学习TCP三次握手和四次挥手 作者:老錢 链接:...

欧阳鹏
2018/07/16
0
0
浅谈TCP(1):状态机与重传机制

TCP协议比较复杂,接下来分两篇文章浅要介绍TCP中的一些要点。 本文介绍TCP的状态机与重传机制,下文讲解流量控制与拥塞控制。 本文大部分内容基于TCP 的那些事儿(上)修改而来,部分观点与...

猴子007
2018/04/03
0
0
Linux高级网络开发奇妙之旅

一、基础理论篇 01、网络协议入门 02、LAN、WAN、WLAN、VLAN 和 VPN 的区别 03、IP 地址介绍 04、广播地址介绍 05、无连接和面向连接协议的区别 06、因特网的IP协议是不可靠无连接的,那为何...

tennysonsky
2015/04/14
0
0
注意!是TCP不是HTTP的3次握手与4次挥手(#...#)

引言 在开发中,时不时会听到关于HTTP的三次握手和四次挥手,在面试中也会被问道HTTP的三次握手和四次挥手,很多开发者可能都会有这这种误解,认为三次握手和四次挥手都是HTTP协议的,实际上,...

鲍康霖
2018/06/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

我为什么要写微信公众号

埋一颗种子,细心呵护,静待她枝繁叶茂,葱郁参天 V2论坛上有个帖子【做程序员最重要的还是一定要有自己的作品】,作者写道: 能有一个作品和你的名字联系在一起,应当成为在职业生涯前期着意...

运维咖啡吧
46分钟前
3
0
数据库

数据库架构 数据库架构可以分为存储文件系统和程序实例两大块,而程序实例根据不同的功能又可以分为如下小模块。 1550644570798 索引模块 常见的问题有: 为什么要使用索引 什么样的信息能成...

一只小青蛙
今天
5
0
PHP常用经典算法实现

<? //-------------------- // 基本数据结构算法 //-------------------- //二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k){ if ( $low <= $high){ $mid = int......

半缘修道半缘君丶
昨天
5
0
GIL 已经被杀死了么?

本文原创并首发于公众号【Python猫】,未经授权,请勿转载。 原文地址:https://mp.weixin.qq.com/s/8KvQemz0SWq2hw-2aBPv2Q 花下猫语: Python 中最广为人诟病的一点,大概就是它的 GIL 了。...

豌豆花下猫
昨天
6
0
git commit message form

commit message一般包括3部分:Header、Body、Footer。 <type>(<scope>):<subject>blank line<body>blank line<footer> header是必需的,body、footer可以省略。 header中type、subject......

ninjaFrog
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部