【解读】TCP三次握手和四次挥手
TCP有6种标识:
1、SYN(建立连接)
2、ACK(确认)
3、PSH(传送)
4、FIN(结束)
5、RST(重置)
6、URG(紧急)
一、TCP三次握手

第一次握手(发送:连接请求)
客户端向服务器,发出连接请求报文,这时报文首部中的同部位SYN=1,同时随机生成初始序列号 seq=x,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状
态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。这个三次握手中的开始。表示客户端想要和服务端建立连接。
第二次握手(确认:同意连接)
TCP服务器,收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己随机初始化一个序列号 seq=y,此
时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。这个报文带有SYN(建立连接)和ACK(确认)标志,询问客户端
是否准备好。
第三次握手(发送:收到确认)
TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。
TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。这里客户端表示我已经准备好。
思考:为什么要三次握手呢,有人说两次握手就好了
举例:已失效的连接请求报文段。
client发送了第一个连接的请求报文,但是由于网络不好,这个请求没有立即到达服务端,而是在某个网络节点中滞留了,直到某个时间才到达server,本来这已经是一个失效
的报文,但是server端接收到这个请求报文后,还是会想client发出确认的报文,表示同意连接。
假如不采用三次握手,那么只要server发出确认,新的建立就连接了,但其实这个请求是失效的请求,client是不会理睬server的确认信息,也不会向服务端发送确认的请求,但是server认为新的连接已经建立起来了,并一直等待client发来数据,这样,server的很多资源就没白白浪费掉了。
采用三次握手就是为了防止这种情况的发生,server会因为收不到确认的报文,就知道client并没有建立连接。
这就是三次握手的作用。
二、TCP数据的传输过程
建立连接后,两台主机就可以相互传输数据了。如下图所示:

1)主机A初始seq为1200,滑动窗体为100,向主机B传递数据的过程。
2)假设主机B在完全成功接收数据的基础上,那么主机B为了确认这一点,向主机A发送 ACK 包,并将 Ack 号设置为 1301。因此按如下的公式确认 Ack 号:
Ack号 = Seq号 + 传递的字节数 + 1 (这是在完全接受成功的情况下)
3)主机A获得B传来的ack(1301)后,开始发送seq为1301,滑动窗体为100的数据。
......
与三次握手协议相同,最后加 1 是为了告诉对方要传递的 Seq 号。
上面说了,主机B完全成功接收A发来的数据才是这样的,如果存在丢包该如何。
下面分析传输过程中数据包丢失的情况,如下图所示:

上图表示:
通过 Seq 1301 数据包向主机B传递100字节的数据,但中间发生了错误,主机B未收到。
经过一段时间后,主机A仍未收到对于 Seq 1301 的ACK确认,因此尝试重传数据。
为了完成数据包的重传,TCP套接字每次发送数据包时都会启动定时器,如果在一定时间内没有收到目标机器传回的 ACK 包,那么定时器超时,数据包会重传。
上面也只是一种可能,比如数据1250丢失,那么Ack返回的就是1250,具体的可以详细看下博客:【解读】TCP协议 ,这里面滑动窗口有说明。
三、TCP的四次挥手

第一次握手(客户端:发送连接释放报文)
TCP发送一个FIN(结束),用来关闭客户到服务端的连接。
客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),
此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
第二次握手(服务器:确认收到释放)
服务端收到这个FIN,他发回一个ACK(确认),确认收到序号为收到序号+1,和SYN一样,一个FIN将占用一个序号。
服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器
通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个
状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
第三次握手(服务器:发送结束(释放连接))
服务端发送一个FIN(结束)到客户端,服务端关闭客户端的连接。
服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,
此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
第四次握手(客户端:发送确认收到)
客户端发送ACK(确认)报文确认,并将确认的序号+1,这样关闭完成。
客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时
TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
服务器只要收到了客户端发出的确认,立即进入CLOSED状态。
同样,撤销TCB后,就结束了这次的TCP连接。
可以看到,服务器结束TCP连接的时间要比客户端早一些。
思考:那么为什么是4次挥手呢?
为了确保数据能够完成传输。
关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;
但未必你所有的数据都全部发送给对方了,所以你未必可以马上关闭SOCKET,
你也可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,
所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
思考:tcp我握手的时候为何ACK(确认)和SYN(建立连接)是一起发送。
挥手的时候为什么是分开的时候发送呢.
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。
其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭 SOCKET,
所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。
只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。
故需要四步握手。
思考:客户端突然挂掉了怎么办?
正常连接时,客户端突然挂掉了,如果没有措施处理这种情况,那么就会出现客户端和服务器端出现长时期的空闲。
解决办法:
在服务器端设置保活计时器,每当服务器收到客户端的消息,就将计时器复位。
超时时间通常设置为2小时。若服务器超过2小时没收到客户的信息,他就发送探测报文段。
若发送了10个探测报文段,每一个相隔75秒,还没有响应就认为客户端出了故障,因而终止该连接。
四、SYN(洪水)攻击
背景
初始化连接的 SYN 超时问题,Client发送SYN包给Server后挂了,Server回给Client的SYN-ACK一直没收到Client的ACK确认,这个时候这个连接既没建立起来,也不能算
失败。这就需要一个超时时间让Server将这个连接断开,否则这个连接就会一直占用Server的SYN连接队列中的一个位置,大量这样的连接就会将Server的SYN连接队列耗尽,
让正常的连接无法得到处理。
目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第
5次发出后,还要等32s,就知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一
个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称SYN flood攻击),用于耗尽Server的SYN队列。
什么是 SYN 攻击
SYN 攻击:攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器
需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。SYN 攻击是一
种典型的 DoS攻击。
如何检测 SYN 攻击?
检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击。
在 Linux/Unix 上可以使用系统自带的netstats 命令来检测 SYN 攻击。
如何防御 SYN 攻击?
SYN攻击不能完全被阻止,除非将TCP协议重新设计。我们所做的是尽可能的减轻SYN攻击的危害,常见的防御 SYN 攻击的方法有如下几种:
1、缩短超时(SYN Timeout)
2、时间增加最大半连接数
3、过滤网关防护SYN
c4、ookies技术
四、TCP和UDP的区别
我这里简单列举几个,因为我还没有研究UDP这个协议。
1、基于连接与无连接;UDP是无连接的,即发送数据之前不需要建立连接
2、TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付
,即不保证可靠交付Tcp通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
【解读】TCP三次握手和四次挥手的更多相关文章
- TCP三次握手及四次挥手详细图解
TCP三次握手及四次挥手详细图解 Andrew Huangbluedrum@163.com 相对于SOCKET开发者,TCP创建过程和链接折除过程是由TCP/IP协议栈自动创建的.因此开发者并不 ...
- 用wireshark抓包分析TCP三次握手、四次挥手以及TCP实现可靠传输的机制
关于TCP三次握手和四次挥手大家都在<计算机网络>课程里学过,还记得当时高超老师耐心地讲解.大学里我遇到的最好的老师大概就是这位了,虽然他只给我讲过<java程序设计>和< ...
- 应聘复习基础笔记1:网络编程之TCP与UDP的优缺点,TCP三次握手、四次挥手、传输窗口控制、存在问题
重要性:必考 一.TCP与UDP的优缺点 ①TCP---传输控制协议,提供的是面向连接.可靠的字节流服务.当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据.TCP提供 ...
- 【HTTP协议】---TCP三次握手和四次挥手
TCP三次握手和四次挥手 首先我们知道HTTP协议通常承载于TCP协议之上,HTTPS承载于TLS或SSL协议层之上 通过上面这张图我们能够知道. 在Http工作之前,Web浏览器通过网络和W ...
- 网络通信 --> TCP三次握手和四次挥手
TCP三次握手和四次挥手 建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 一.TCP报文格式 如下图: (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发 ...
- 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手
.引言 网络编程中TCP协议的三次握手和四次挥手的问题,在面试中是最为常见的知识点之一.很多读者都知道“三次”和“四次”,但是如果问深入一点,他们往往都无法作出准确回答. 本篇文章尝试使用动画图片的方 ...
- TCP‘三次握手’和‘四次挥手’(通俗易懂)
概述 我们都知道 TCP 是 可靠的数据传输协议,UDP是不可靠传输,那么TCP它是怎么保证可靠传输的呢?那我们就不得不提 TCP 的三次握手和四次挥手. 三次握手 下图为三次握手的流程图 下面通 ...
- 【转】TCP三次握手和四次挥手全过程及为什么要三次握手解答
TCP三次握手和四次挥手的全过程 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位,有6种表示: SYN(synchronous建立连接) ...
- [ 转载 ] Tcp三次握手和四次挥手详解
#TCP的报头: 源端口号:表示发送端端口号,字段长为16位.目标端口号:表示接收端口号,字段长为16位.序列号:表示发送数据的位置,字段长为32位.每发送一次数据,就累加一次该数据字节数的大小.注意 ...
- 网络协议-网络分层、TCP/UDP、TCP三次握手和四次挥手
网络的五层划分是什么? 应用层,常见协议:HTTP.FTP 传输层,常见协议:TCP.UDP 网络层,常见协议:IP 链路层 物理层 TCP 和 UDP 的区别是什么 TCP/UDP 都属于传输层的协 ...
随机推荐
- [PHP学习教程 - 日期/时间]001.月份第一天&最后一天(Month First Day & Last Day)
引言:在时间处理上,对于前/后台人性化的展示当前月份最大天数,这个是网站必须要处理的一个方面.但通常这一块会由第三方类库直接包装,这里我们做一个简单的Mark. 今天,我们就为大家提供一个函数,获得指 ...
- [PHP自动化-进阶]005.Snoopy采集框架介绍
引言:Snoopy是一个php类,用来模仿web浏览器的功能,它能完成获取网页内容和发送表单的任务. **官方网址:http://snoopy.sourceforge.net/** 简单一句话表达:& ...
- Jenkins在Pod中实现Docker in Docker并用kubectl进行部署
Jenkins在Pod中实现Docker in Docker并用kubectl进行部署 准备工作 安装Jenkins Jenkins的kubernetes-plugin使用方法 说明 Jenkins的 ...
- try catch finally return 轶事
最近阿里发布了java开发手册终极版,看到其中一条规约:[强制]不能在 finally 块中使用 return, finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 ...
- Bitwarden_rs搭建
最近LastPass网络极其不稳定,正好闲下来找到了Bitwarden_rs这个替代品,感觉不错,分享记录下部署过程. 一.Docker方式部署 #获取镜像 docker pull bitwarden ...
- java中的垃圾处理机制
1.何为垃圾在Java中,如果对象实体没有引用指向的话,存储该实体的内存便成为垃圾.JVM会有一个系统线程专门负责回收垃圾.垃圾同时包括分配对象内存间的碎片块 2.垃圾处理包含的算法 Java语言规范 ...
- JAVASE(十六) IO流 :File类、节点流、缓冲流、转换流、编码集、对象流
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.File类型 1.1.File类的理解 File类是在java.io包下 File可以理解成一个文件 ...
- 判断IP地址的合法性
每台计算机都有独一无二的编号,称为ip地址,每个合法的ip地址由‘.’分隔开的4个数字组成,每个数字的取值范围为0--255 输入一个字符串,判断其是否为合法的IP地址,若是输出‘YES’,否则输出‘ ...
- Java实现 LeetCode 752 打开转盘锁(暴力)
752. 打开转盘锁 你有一个带有四个圆形拨轮的转盘锁.每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' .每个拨轮可以自由旋 ...
- Java实现 LeetCode 693 交替位二进制数(位运算)
693. 交替位二进制数 给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等. 示例 1: 输入: 5 输出: True 解释: 5的二进制数是: 101 示 ...