TCP连接建立(三次握手)

如图:

  1. 请求端发送一个SYN到服务器的相应端口,以及初始序号ISN
  2. 服务器发送包含服务器的初始序号的SYN作为应答,同时确认序号设置为客户的ISN+1
  3. 客户将确认序号设置为服务器的ISN+1

最大报文段长度(MSS)

  • 连接建立时,连接的双方都要通告各自的MSS。当建立一个连接时,每一方都有通告它期望接收的MSS选项。如果一方不接收来自另一方的MSS值,则MSS就定为576字节。对于一个以太网,MSS可达1460字节(1460 + IP首部20 + TCP首部20 = 1500)。如果目的IP地址是“非本地的”, MSS通常的默认值是536。
  • MSS让主机限制另一端发送数据报的长度,加上主机也能控制它发送数据报的长度,这将使以较小MTU连接到一个网络的主机避免分段。
  • 如果两端的主机都连接到以太网上,都采用536的MSS, 但中间网络采用296的MTU,也将会出现分段, 使用路径上的MTU发现机制是关于这个问题的唯一方法。

同时打开

一般情况下,连接建立时是一方发送SYN,另一方发送SYN+ACK, 但极个别情况下,有可能两个应用程序几乎同时向对方发送SYN,这就叫做同时打开。同时打开需要双方都使用彼此熟知的端口,而不是一般情况下只需要客户使用服务器的知名端口。

TCP的同时打开的状态变迁图如下:



两端几乎同时发送SYN,并进入SYN_SENT状态。当每一端收到SYN时,状态变为SYN_RCVD,同时它们都再发SYN并对收到的SYN进行确认。当双方都收到SYN及相应的ACK时,状态都变迁为ESTABLISHED。

呼入连接请求队列

有可能出现当服务器在创建一个新的进程时,或操作系统正忙于处理优先级更高的进程时,到达多个连接请求,当服务器处于忙时,TCP是如何处理这些呼入的连接请求?

在伯克利的TCP实现中采用以下规则:

  1. 正等待连接请求的一端有一个固定长度的连接队列,该队列中的连接已被TCP接受(即三次握手已完成),但还没有被应用层所接受。注意区分TCP接受一个连接是将其放入队列,而应用层是将其从该队列中移出。
  2. 应用层将指明该队列的最大长度,这个值称为积压值。它的取值范围是0~5之间的整数。
  3. 当一个连接请求到达时,TCP使用一个算法,来确定是否接收这个连接。
  4. 如果对于新的连接请求,该TCP监听的端点的连接队列中还有空间,TCP模块将对这个SYN进行确认并完成连接的建立。但应用层只有在三次握手中的第三个报文段才能知道这个新连接。另外,当客户进程的主动打开成功但服务器的应用层还不知道这个新的连接时,它可能会认为服务器进程已经准备好接收数据了(如果发生这种情况,服务器的TCP仅将接收的数据放入缓冲队列)。
  5. 如果对于新的连接请求,连接队列已没有空间,TCP将不理会收到的SYN,也不发回任何报文段(即不发回RST),如果应用层不能及时接受已被TCP接受的连接,这些连接可能占满整个连接队列,客户的主动打开将最终超时。

    当队列已满时,TCP将不理会收到的SYN,也不发回任何报文段(即不发回RST),因为这是一个软错误,而不是一个硬错误。通常队列已满是由于应用程序或操作系统忙造成的,这样可防止应用程序对传入的连接进行服务。这个条件在很短的时间内可以改变。但如果服务器的TCP以系统复位作为响应,客户进程的主动打开将被废弃。由于不应答SYN,服务器程序迫使客户TCP随后重传SYN,以等待连接队列有空间接受新的连接。

TCP连接终止(四次握手)

既然一个TCP连接是全双工的(即数据在两个方向上都能传递),因此每个方向都必须单独进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向上的连接。当一端收到一个FIN,它必须通知应用层另一端已经终止了那个方向的数据传送。

如下图:

半关闭

TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭。

如下图:

2MSL等待状态

TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL。它是任何报文段被丢弃前在网络内的最长时间。

为什么要有TIME_WAIT状态?

  • 因为终止连接的一方发送的最后的一个ACK可能会丢失,另一端超时并重发最后的FIN, 这样终止连接的一方可以再次发送最后的ACK

为什么是2MSL?

  • 最后一个ACK存在的时间最多为MSL,如果ACK丢失,然后接收端超时并重发FIN,这个FIN最多存在时间又是MSL,而TIME_WAIT状态需要等待这个连接中的所有分组都消失,所以需要等待2ML
  • 2MSL时间后这个连接的所有分组都会消失,不会干扰到接下来相同socket对建立的连接。

TCP在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用,这个连接只能在2MSL结束后才能再被使用。如果我们终止一个已经建立连接的服务器程序,并试图立即重启这个服务器程序,服务器程序不能把它的这个熟知端口赋值给它的端点,因为那个端口是出于2MSL连接的一部分。

我们可以以-A标记来设置SO_REUSEADDR,这样可以使服务器程序使用之前的端口,但它不能主动打开之前的相同端口的客户程序,应为那个连接的插口对仍处于2MSL等待状态。但我们如果让那个客户程序来主动打开这个服务器程序是会成功的,因为大多数的伯克利实现支持一个新的连接请求到达仍处于TIME_WAIT状态的连接。

复位报文段

一般说来,无论何时一个报文段发往指定的连接出现错误,TCP都会发出一个复位报文段。

产生复位的几种常见情况是:

  • 到不存在的端口的连接请求;
  • 异常终止一个连接;
  • 检测半打开连接。

    如果一端已经关闭或异常终止连接而另一方却还不知道,我们将这样的连接成为半打开连接。

    同时关闭

    两边都执行主动关闭也是有可能的,TCP协议也允许这样的同时关闭。

    如下图:

部分问题

  1. 为什么服务器对客户FIN的ACK不和自己的FIN合并(即终止连接不是三次握手)?

    因为发送客户FIN的ACK通常是收到FIN就立刻发送,但这是服务器不一定要关闭自己这端的连接,还可能需要发送数据(半关闭),所以不一定要发送FIN。
  2. 分析处于TIME_WAIT状态的主机收到使其进入此状态的重复的FIN时所发生的情况

    发送ACK,重启定时器。

TCP连接建立和终止小结的更多相关文章

  1. 动手学习TCP:TCP连接建立与终止

    TCP是一个面向连接的协议,任何一方在发送数据之前,都必须先在双方之间建立一条连接.所以,本文就主要看看TCP连接的建立和终止. 在开始介绍TCP连接之前,先来看看TCP数据包的首部,首部里面有很多重 ...

  2. TCP连接建立与终止,及状态转换

    TCP连接建立 三路握手 三路握手发生在客户端发起connect请求到服务端accept返回中,在三路握手发生前,服务端必须准备好接受外来连接,这通常通过服务端调用 (socket.bind.list ...

  3. 关于TCP连接建立与终止那点事

    0. 前言 最近在处理公司遗留项目的时候发现自己对TCP协议一点都不懂,所以补了点关于TCP连接的建立和终止的内容,这里简单写下自己了解的部分,省略了报文序号确认序号这些无关的字段,主要讨论TCP状态 ...

  4. 传输控制协议(TCP) -- 连接建立及终止过程

    TCP简介 相对于不可靠.无连接的用户数据报协议(User Datagram Protocol, UDP),传输控制协议(Transmission Control Protocol, TCP)是可靠的 ...

  5. TCP连接建立和关闭中的疑难点

    TCP连接建立和关闭中的疑难点 作者:夏语岚    撰写日期:2011-10-29 近日在阅读<Unix网络编程>,以前在<计算机网络>课程中学到TCP,当时只是简单了解了TC ...

  6. TCP连接建立与关闭

    http://hi.baidu.com/psorqkxcsfbbghd/item/70f3bd91943b9248f14215cd TCP连接建立与关闭 TCP 是一个面向连接的协议,无论哪一方向另一 ...

  7. tcp、http 学习小结

    tcp.http 学习小结 前言 最近因为cdn的一个问题,困扰了自己好久.因为需要统计网站访问的成功数,而且要求比较精确.目前的实现不能满足要求,因为没有区别访问成功与否,也没有对超时做处理.期间解 ...

  8. 计算机网络传输层之TCP协议(tcp协议特点、tcp报文段首部格式、tcp连接建立---三次握手、tcp连接释放---四次握手)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105516090 学习课程:<2019王道考研计算机网络> 学习目的 ...

  9. 《TCP/IP详解 卷一》读书笔记-----TCP连接建立

    1.在每个TCP报文段中,头部的flag字段里的SYN,FIN,RST,PSH可以多个有效,并没有限定为必须只有一个 2.TCP连接建立过程: 1)客户端发送一个SYN报文段,其中包含了客户端要传送的 ...

随机推荐

  1. 06.移动先行之谁主沉浮----我的代码我来写(Xaml的优势)

    如果移动方向有任何问题请参考===> 异常处理汇总-移动系列(点) 前面几节课,我们都是在前台创建对象,进行一些设置,那么我们为什么不用传统的方法来编程呢? 我们今天来试试你就明了了~~ 打开M ...

  2. 【.NET深呼吸】元组数据(Tuple)

    各位观众,大家好,欢迎收看由火星电视台直播的<老周吹牛>节目,注意:本节目没有任何技术含量,如果您没有兴趣,请砸掉电视机. 今天说一下System命名空间下的一个数据类型——Tuple,翻 ...

  3. Node+fs+定时器(node-schedule)+MySql

    目标:将本人写博客时候的截图保存到桌面的图片 执行保存到指定文件进行整理 并写入数据库 先看最终的目录结构: package.json文件: { "name": "zqz ...

  4. iOS 支持 IPv6

    苹果的规定:2016年6月1日提交到App Store必须支持IPv6-only网络. 官方文档:https://developer.apple.com/library/mac/documentati ...

  5. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  6. 浅析MySQL基于ROW格式的二进制日志

    上文分析的二进制日志实际上是基于STATEMENT格式的,下面我们来看看基于ROW格式的二进制日志,毕竟,两者对应的binlog事件类型也不一样,同时,很多童鞋反映基于ROW格式的二进制日志无法查到原 ...

  7. url 编码(percentcode 百分号编码)(转载)

    原文地址:http://www.cnblogs.com/leaven/archive/2012/07/12/2588746.html   http://www.imkevinyang.com/2009 ...

  8. 【分布式】Zookeeper使用--Java API

    一.前言 上一篇博客我们通过命令行来操作Zookeper的客户端和服务端并进行相应的操作,这篇主要介绍如何通过API(JAVA)来操作Zookeeper. 二.开发环境配置 首先打开Zookeeper ...

  9. IL接口和类的属性

    上一篇文章学习了IL的入门,接下来我们再通过两个例子来了解下类的属性.构造函数以及接口的使用 一.类的属性.构造函数 1.先看下我们要构建的类的C#代码,然后再进行IL的实现,示例代码如下: [Ser ...

  10. 在DevExpress程序中使用内置的图标构建美观的界面元素

    在我们一般的程序中,为一般的界面元素添加一定的图标展示,有助于提升界面的整体的美观.结合排版布局,以及固定场景的图标,往往给用户非常好的直观感受:统一.美观.易理解.因此在一般的程序界面中,都尽量在略 ...