TCP学习总结(四)
TCP连接管理
TCP运输连接有3个阶段, 即: 连接建立,数据传送和连接释放。
1. TCP的连接建立(3次握手)
TCP连接的建立采用客户服务器方式。主动发起连接建立的应用进程叫做客户(client), 而被动等待连接建立的应用进程叫做服务器(server)。
TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的。
看图讲解。

1.第一次握手:建立连接。客户端(A)发送连接请求报文段, SYN置为1,seq(Sequence Number)=x。TCP规定,SYN报文段(SYN为1,ACK为0的报文段)不能携带数据,但要消耗掉一个序号。然后,客户端进入SYN-SENT(同步已发送)状态,等待服务器的确认。
2.第二次握手:服务器(B)收到SYN报文段。服务器收到客户端的SYN报文段,还需要对这个SYN报文段进行确认。SYN置为1,ACK置为1(可以到第一章头部信息查看这样代表什么意思),ack(Acknowledgment Number)=x+1(seq+1),seq=y,服务器端将上述所有信息放到一个报文段中(这个报文段也不能携带数据,但同样要消耗一个序号),一并发送给客户端,此时服务器进入SYN-RECVD状态;
3.第三次握手:客户端收到服务器的SYN+ACK报文段。然后将seq设置为x+1(下一个报文段),ack设置为y+1,向服务器发送ACK报文段(即SYN为0,ACK为1的报文段),这个报文段发送完毕以后,客户端进入ESTABLISHED状态,服务器端收到确认后,也进入ESTABLISHED状态,完成TCP三次握手。
为什么客户端A还要发送一次确认,进行第3次握手呢?主要是为了防止"已失效的连接请求报文段"突然又传到了服务端B,因为产生错误。
所谓"已失效的连接请求报文段"是这样产生的:
一种正常情况。A发出连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接,然后收到了重传连接的确认,建立连接,数据传输完毕,释放了连接。由于第一个是丢失了,第二个到达了B,所以没有"已失效的连接请求报文段"。
第二种异常情况。即A发出的第一个请求没有丢失,而是在某个网络节点滞留了,以致延误到连接释放以后的某个时间才到达B。本来就是一个失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求。新的连接就建立了。
由于现在A并没有发出连接请求,因此不会理睬B的确认,也不会向B发送数据。而B以为新的运输连接已经建立了,并一直等待A发来数据。B的许多资源就这样白白浪费了。
而A发送第三次握手,就可以防止上述现象的发送:
就上述情况,A不会向B的第二次握手发出确认。B由于收不到确认,超时后就不会为此建立连接。
2. TCP的连接释放(4次挥手)
先上图,有图说得更清楚。

步骤:
1. 挥手1: 首先客户端A发送释放连接报文段: FIN置为1, seq=已传送最后一个字节的序号+1,并停止再发送数据。这时A进入FIN-WAIT-1(终止等待1)状态,等待服务器B的确认。FIN报文段即时不携带数据,它也消耗一个序号!
2. 挥手2: 服务器B收到连接释放报文段后发出确认报文段: ACK置为1,seq=v,ack=u+1。然后B进入CLOSE-WAIT(关闭等待)状态。这时TCP的连接处于半关闭(half-close)状态,即A已经没有数据发送来,若B发送数据,A仍要接收。
3. 客户端A收到B的确认报文段后,进入FIN-WAIT-2(终止等待2)状态。等待B发出的连接释放报文段。
4. 挥手3: 如果B已经没有要向A发送的数据,B就发出连接释放报文段: FIN、ACK置为1,seq=w(在半关闭状态的B可能还发送来一些数据),ack=u+1(必须重复上一次已发送过的确认号)。这时B进入LAST-ACK(最后确认)状态,等待A的确认。(如果在第一次挥手后,B没有数据需要A接收,那就直接进行第三次挥手,这样,四次挥手就变成了三次挥手了)
5. 挥手4: A在收到B的连接释放报文段后,发出确认: ACK置为1,ack=w+1,seq=u+1(步骤1那已经消耗了一个序号,所以这里是u+1)。然后进入TIME-WAIT(时间等待)状态。B收到这个确认后进入CLOSED状态,关闭连接。
注意,现在TCP连接还没有释放掉,必须在经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL(时间MSL叫最长报文段寿命,RFC793建议设为2分钟)后,A才进入CLOSED状态。
为什么A在TIME-WAIT状态必须等待2MSL,一共就是4分钟这么长呢?
1. 为了保证A发送的最后一个ACK能到达B!
因为这个ACK报文段有可能丢失,B就一直处于LASK-ACK状态,然后B超时重传第三次挥手发送的FIN+ACK连接释放报文段,这时A就能在2MSL时间内收到这个重传的FIN+ACK报文段。然后A就在重传一次挥手4发送的连接ACK报文段,再重新启动2MSL计时器。最后A和B就都能正常进入到CLOSED状态。
2. 防止3次握手中提到的"已失效的连接请求报文段"出现!
A发送完最后一次ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
通过下面例子说明:
假设tcp连接是: A(1.2.3.4:8888)------B(6.7.8.9:9999), 这就是一个tcp四元组。 当tcp连接关闭后, 四元组释放。 后面的新连接可能会重用到这个四元组(有这个可能性), 那么问题就来了: 新四元组和旧四元组完全一致, 他们的网络包会混乱吗? 所以, 可以考虑这样一个机制: 让旧四元组对应的所有网络包都消失后(等一段时间), 才允许新四元组建立, 颇有点锁的味道。
保活计时器(keepalive timer)
除了上述提到的时间等待计时器外,TCP还设有一个保活计时器!
设想这样种情况: 客户端主动与服务端建立TCP连接后,过了一段时间,客户端机器突然故障宕机了!服务端就再也无法收到客户端发来的数据,服务器不能白白干等着!保活计时器就是解决这个问题的:服务端每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是2小时。
若2小时内没有收到客户端的数据,服务器还是不会放弃它的!就会发送一个探测保文段,以后每隔75分钟发送一次。若连续发送了10次探测保文段后,客户端仍无响应,服务器就认为客户端出现了故障,然后就关闭了这个连接。
TCP学习总结(四)的更多相关文章
- redis学习教程四《管理、备份、客户端连接》
redis学习教程四<管理.备份.客户端连接> 一:Redis服务器命令 Redis服务器命令 下表列出了与Redis服务器相关的一些基本命令. 序号 命令 说明 1 BGREWRITE ...
- Java IO学习笔记四:Socket基础
作者:Grey 原文地址:Java IO学习笔记四:Socket基础 准备两个Linux实例(安装好jdk1.8),我准备的两个实例的ip地址分别为: io1实例:192.168.205.138 io ...
- Netty 学习(四):ChannelHandler 的事件传播和生命周期
Netty 学习(四):ChannelHandler 的事件传播和生命周期 作者: Grey 原文地址: 博客园:Netty 学习(四):ChannelHandler 的事件传播和生命周期 CSDN: ...
- 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式
本系列文章导航 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式 一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得 ...
- 前端学习 第四弹: HTML(一)
前端学习 第四弹: HTML(一) 元素分类:块元素 内联元素 块级元素在浏览器显示时,通常会以新行来开始(和结束). 例子:<h1>, <p>, <ul>, &l ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- Android Animation学习(四) ApiDemos解析:多属性动画
Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...
- 五、Android学习第四天补充——Android的常用控件(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 五.Android学习第四天补充——Android的常用控件 熟悉常用的A ...
- 四、Android学习第四天——JAVA基础回顾(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...
随机推荐
- python高阶函数(Map、Reduce、Filter、lamba)
Map函数 map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. 代码如下: >>> def f(x): . ...
- jmeter的安装和配置
jmeter环境配置 Java 8 安装 正常安装,一路默认就好,记住安装路径,配置环境变量时用得到.默认安装路径:C:\Program Files\Java\jdk1.8.0_91. 安装好之后会有 ...
- oracle drop 表后 恢复
1.查看回收站中表 select object_name,original_name,partition_name,type,ts_name,createtime,droptime from recy ...
- vue 渲染后更新数据
this.$set(this.selGetData,level,[{},{}])this.$set(this.selGetData,1,{message:"Test add attr&quo ...
- Spring的事务初见
一.事务的特性 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 一致性: 执行事务前后,数据保持一致: 隔离性: 并发访问数据库时,一个用户的事物不被 ...
- WCF:一个棘手的问题
前言 在做即时通信项目时,手上另一个项目的颠簸,即时通信项目一直是改改停停的,一些改动比较小,没有即时的签入,然后一段时间本地的项目代码与源代码存在不少区别,在这种情况下,因为新的需求添加,需要给WC ...
- CentOS 中安装和卸载 Emacs
日志更新记录: [1] 增加 CentOS7.2 (内核版本:3.10.0-514.16.1.el7.x86_64)下Emacs25.2 的安装过程,它与本文的步骤完全一样. Emacs 版本:htt ...
- 【安全测试】如何利用短信验证码BUG浪费公司的钱
一.背景 公司新产品体验,发现不少交互.UI.功能设计上的小问题.于是花了点时间随意挑了几个功能深入的玩了一下,顺手提了BUG.接口层,看了一下接口文档,简单测了一下接口,BUG其实还挺严重的,后面详 ...
- Spring实现WebSocket通信
WebSocket是两个应用之间全双工的通信通道.WebSocket最常见的应用场景是实现服务器和基于浏览器的应用之间的通信. 浏览器中的javascript客户端开启一个到服务器的连接,服务器通过这 ...
- UVa LA 3266 - Tian Ji -- The Horse Racing 贪心,不只处理一端,也处理另一端以理清局面 难度: 2
题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...