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学习总结(四)的更多相关文章

  1. redis学习教程四《管理、备份、客户端连接》

    redis学习教程四<管理.备份.客户端连接>  一:Redis服务器命令 Redis服务器命令 下表列出了与Redis服务器相关的一些基本命令. 序号 命令 说明 1 BGREWRITE ...

  2. Java IO学习笔记四:Socket基础

    作者:Grey 原文地址:Java IO学习笔记四:Socket基础 准备两个Linux实例(安装好jdk1.8),我准备的两个实例的ip地址分别为: io1实例:192.168.205.138 io ...

  3. Netty 学习(四):ChannelHandler 的事件传播和生命周期

    Netty 学习(四):ChannelHandler 的事件传播和生命周期 作者: Grey 原文地址: 博客园:Netty 学习(四):ChannelHandler 的事件传播和生命周期 CSDN: ...

  4. 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式

    本系列文章导航 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式 一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得 ...

  5. 前端学习 第四弹: HTML(一)

    前端学习 第四弹: HTML(一) 元素分类:块元素 内联元素 块级元素在浏览器显示时,通常会以新行来开始(和结束). 例子:<h1>, <p>, <ul>, &l ...

  6. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  7. Android Animation学习(四) ApiDemos解析:多属性动画

    Android Animation学习(四) ApiDemos解析:多属性动画 如果想同时改变多个属性,根据前面所学的,比较显而易见的一种思路是构造多个对象Animator , ( Animator可 ...

  8. 五、Android学习第四天补充——Android的常用控件(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 五.Android学习第四天补充——Android的常用控件 熟悉常用的A ...

  9. 四、Android学习第四天——JAVA基础回顾(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 四.Android学习第四天——JAVA基础回顾 这才学习Android的 ...

随机推荐

  1. 第 9 章 数据管理 - 073 - 如何实现跨 Docker 主机存储?

    从业务数据的角度看,容器可以分为两类: 无状态(stateless)容器 无状态是指容器在运行过程中不需要保存数据,每次访问的结果不依赖上一次访问,比如提供静态页面的 web 服务器. 有状态(sta ...

  2. [大数据面试题]storm核心知识点

    1.storm基本架构 storm的主从分别为Nimbus.Supervisor,工作进程为Worker. 2.计算模型 Storm的计算模型分为Spout和Bolt,Spout作为管口.Bolt作为 ...

  3. HBase表数据的转移之使用自定义MapReduce

    目标:将fruit表中的一部分数据,通过MR迁入到fruit_mr表中 Step1.构建ReadFruitMapper类,用于读取fruit表中的数据 package com.z.hbase_mr; ...

  4. liunx-centos的安装学习篇

    1.centos下载地址:网易镜像:http://mirrors.163.com/centos/6/isos/搜狐镜像:http://mirrors.sohu.com/centos/6/isos/ 2 ...

  5. Django web框架-----Django templates模板

    说明:mytestsite是django框架下的项目,quicktool是mytestsite项目中的应用 一般的变量之类的用 {{ }}(变量),功能类的比如循环.条件判断是用 {% %}(标签) ...

  6. SWUST OJ(1038)

    顺序表中重复数据的删除 #include <iostream> #include <cstdlib> using namespace std; int main() { int ...

  7. LVM方式安装Ubuntu 系统

    重装Ubuntu系统,使用LVM管理磁盘,最好不要使用默认的LVM安装方式,而应挂载U盘启动盘,进行物理磁盘分区,创建物理卷.卷组.虚卷(即创建LVM系列操作),在安装系统时将虚卷挂载到文件目录上.将 ...

  8. liunx定时任务

    为当前用户创建cron服务 1.  键入 crontab  -e 编辑crontab服务文件 例如 文件内容如下: */2 * * * * /bin/sh /home/admin/jiaoben/bu ...

  9. windows下Xshell远程访问虚拟机

    下载Xshell 5软件在windows下安装 安装好后Xshell 5启动软件 下一步,检查虚拟机,配置是否正确 下一步,设置网络,保障虚拟机系统能够连接网络 下一步,进入虚拟机系统,检查虚拟机网络 ...

  10. 微信小程序实战练习(仿五洲到家微信版)

    github地址(欢迎star):https://github.com/xiaobinwu/dj 版本:0.15.152900(暂未升级原因:升级后需要图片无法本地引用,必须使用image或是远程路径 ...