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. chat聊天系统项目

    项目名称:实现一个在线聊天系统? 一.需求 1. 海量用户在线聊天系统:2. 用户登录注册:3. 根据用户ID或者Nickname搜索并添加用户:4. 动态知道好友上下线:5. 可以创建群并添加好友到 ...

  2. SpringBoot+mybatis:报错Fri Oct 19 14:29:24 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requiremen

    报错:Fri Oct 19 14:29:24 CST 2018 WARN: Establishing SSL connection without server's identity verifica ...

  3. CF #552(div3)G 最小lcm

    题目链接:http://codeforces.com/contest/1154/problem/G 题意:lcm是最小公倍数,本题就是给你一个数组(可能会重复),要求你判断出那两个数的最小公倍数最小, ...

  4. CF 552(div 3) E Two Teams 线段树,模拟链表

    题目链接:http://codeforces.com/contest/1154/problem/E 题意:两个人轮流取最大值与旁边k个数,问最后这所有的数分别被谁给取走了 分析:看这道题一点思路都没有 ...

  5. class类初始化之后调用赋值问题记录

    class PWSTRDELL: def __init__(self, pw_str):#该方法在类实例化时会自动调用 self.pw = pw_str self.strength_level = 0 ...

  6. Flask Vue.js全栈开发

    Flask Vue.js全栈开发的 最新完整代码 及使用方式 本系列的最新代码及使用方式将持续更新到: http://www.madmalls.com/blog/post/latest-code/ 1 ...

  7. switch与if语句的应用

    C语言自学之switch与if语句的应用 #include<stdio.h> #include<stdlib.h> int main() { ;//需要计算的年份 ;//需要计 ...

  8. Web API学习——Web API 强势入门指南

    Web API是一个比较宽泛的概念.这里我们提到Web API特指ASP.NET Web API. 这篇文章中我们主要介绍Web API的主要功能以及与其他同类型框架的对比,最后通过一些相对复杂的实例 ...

  9. div凹角实现

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. 【转】FluentAPI详细用法

    设置主键modelBuilder.Entity<x>().HasKey(t => t.Name); 设置联合主键modelBuilder.Entity<x>().HasK ...