TCP连接管理

  本节将介绍一条TCP连接是如何建立和拆除的。此处假设客户机A上面的一个进程想要和服务
器B上的一个进程建立一条TCP连接。本文前面介绍的是比较正常的连接和拆除,特殊的会在后面介绍。

TCP连接建立

        

第一步

客户机A的TCP会向服务器的TCP发送一个不包含应用层数据的数据的TCP报文段。该报文段中首部标志位S YN被置为1,此报文段也被叫做SYN报文段。并且A会随机地选择一个初始序号(client_isn),将其填入首部中的序号字段(注意为了避免某些安全性的攻击,此处的随机化选择有着不少研究,后面会补充)。然后,该报文被封装进IP数据报,发送给服务器。

第二步

一旦TCP SYN报文段的IP数据包到达服务器后,服务器就会从IP数据包中提取出TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户机发送允许TCP连接的报文段,这个报文段也不包含应用层数据。(这里需要注意如果在完成三次握手的第三步之前分配缓存和变量会使得TCP易受到称为SYN洪泛的拒绝服务攻击服务)

在发送的报文中,标志位SYN被置为1,确认序号被置为client_isn+1,
服务器也会选用一个初始序号将其放入报文中的序号字段。这个报文有时也会被称为SYNACK报文段(SYNACK segment)。

第三步

在收到SYNACK报文段后,客户也要给这个连接分配缓存和变量。然后,客户机A会向服务器发送对允许连接
报文的确认,完成连接的建立。此时报文中,SYN置为0,确认序号为sever_isn+1。在此报文段中也可以携带客户机到服务器的数据了。

完成这三个步骤后,客户机和服务器就可以相互发送包含数据的报文段啦。在以后的每个报文中SYN都为0。
创建连接需要发送三个报文,所以这个过程也叫3次握手(three-way shakehand)

那么问题也出来了。为什么需要三次握手,只交换两次报文不可以吗?
可以简单地解释下,客户发送确认服务器发送的接收连接报文是为了防止以前的连接请求即失效连接请求发送到服务器而造成错误。

TCP连接释放

有连接必然就有释放的时候。释放的过程可以见下图。

   

                   TCP连接释放示意图

第一步

客户进程发出关闭TCP连接命令。客户TCP便会向服务器进程发送标志位FIN=1的报文段,便进入FIN_WAIT_1阶段。服务器TCP收到该报文段后就向客户机发送确认报文段并通知上层应用程序该TCP连接即将关闭,然后,服务器进入CLOSE_WAIT阶段。

第二步

客户机TCP收到确认报文,然后进入FIN_WAIT_2阶段,等待来自服务器的含有FIN=1的报文段。
服务器在这段时间还是可以向客户机发送含上层应用程序数据的报文段,客户机接收并发送确认报文。最后,服务器TCP向客户机发送含FIN=1的报文段,便进入LASE_ACK阶段。

第三步

客户机TCP收到含FIN=1的报文段向服务器发出确认报文,便进入TIME_WAIT阶段,等待2MSL后便释放所有连接所占资源。如果客户给服务器发送的确认报文丢失,那么在这段时间内,便可进行重传操作。这段时间一过,客户将释放所有连接所占资源。
服务器TCP收到客户机的确认ACK后便释放连接所占资源。

附图两张客户机和服务器在整个TCP连接期间的状态序列

        

        

SYN洪泛攻击

记得在前面说过服务器收到一个SYN后,会分配缓存并初始化一些相关变量。然后向客户发送SYNACK进行响应,并等待来自客户的ACK报文段。如果某个客户不发送ACK完成三次握手的第三步,最终(通常在一分多钟后)服务器将终止该半开连接并回收资源。
这种TCP连接管理协议为经典的DoS攻击即SYN洪泛攻击(SYN flood attack)提供了环境。在这种攻击中,攻击者发送大量的TCP SYN报文段,而不完成三次握手中的第三步,服务器为大量的这种半开连接分配资源,最终将导致服务器的连接资源殆尽。
好的是,现在有一种有效的防御系统——SYN cookie [RFC 4987],其工作方式可以描述如下:

  • 当服务器接收到一个SYN报文时,不为该报文段生成一个半开连接。相反,服务器为其生成一个初始TCP序列号,该序列号是用SYN报文段的源和目的IP地址与端口号以及仅有该服务器知道的秘钥生成的散列函数值。这个初始序列号也被叫做"cookie"。服务器向发出连接请求的客户发送TCP序号字段为这个初始序号的SYNACK分组 。
    但是最要的是,服务器并不记忆该初始序号和其他有关这个SYN报文段的信息

  • 如果客户是合法的,那么它会发送一个ACK报文段。当服务器收到该ACK后,需要验证该ACK是与前面发送的某些SYN相对应。
    服务器将使用在SYNACK报文段中的源和目的IP地址与端口号和秘钥运行相同的散列函数,计算该ACK报文段的散列函数值。如果散列函数值加1等同于客户发来的这个ACK中确认号字段的值,那么,服务器就认为该ACK报文段对应于较早的SYN报文段,因此它是合法的。然后,服务器生成一个具有套接字的全开连接!


    以上是正常的连接和释放的过程,下面会对上面进行一些补充。


TCP连接建立和释放的特殊情况

TCP半关闭

TCP支持半关闭操作,如前描述的释放连接第二步中,客户机发送了一个FIN报文给服务器,服务器发送了确认后,客户机这边就进入半关闭状态,但是仍然可以接收来自服务器发送的数据。即“我完成了数据的发送工作,并发送了一个FIN给对方,但是我任然希望收到来自对方的数据直到它发送给一个FIN给我”。在服务器未发送FIN的这段时间里,它可以传任意数量的报文段给客户。当服务器发送FIN然后FIN被确认,那么整个连接将完全被关闭。

同时打开与关闭

两个应用程序同时主动打开连接可能不大可能,但是在特定安排的情况下还有可能实现。这要求通信双方收到对方SYN之前必须先发送一个SYN,两个SYN必须经网络到达对方,并要求通信双方告知对方其IP地址和端口号。服务器始终未被动打开,所以不会出现这种情况。
与正常连接相比,多了一个报文段。数据包的SYN将置位直到接收到一个ACK数据包为止。
  

同时关闭与前面的正常关闭并没有太大的区别。在通信中,双方都会主动发送FIN,然后进行关闭。
同时关闭和正常关闭是相同数量的报文段。两者真正的区别在于报文段序列是交叉的还是顺序的。

重置报文段

将TCP首部RST字段置位的报文段被称为“重置报文段”或者“重置”。一般来说,当发现一个到达的报文段对于相关连接而言不正确时,TCP会发送一个重置报文段。(此处,相关连接是指由重置报文段的TCP与IP首部的四元组所指定的连接)。

针对不存在的端口的连接请求

通常,当一个连接请求到达本地却没有相关进程在目的端口侦听时就会产生重置报文段。
UDP协议中规定,当一个数据报到达不能使用的目的端口时就会生成一个ICMP目的地不可达(端口不可达)的消息。
TCP则是使用重置报文段来代替相关工作。
对于被TCP重置的报文段而言,它的ACK位字段必须被置位,并且ACK号字段的数值必须在正确窗口范围内。这样有助于防止他人攻击。

终止一条连接

终止一条正常连接的方法是由通信一方发送FIN。这种方法也被称为有序释放。在这种情况下,TCP缓存中所有排队的数据都被发送,通常没有数据丢失。
然而,在任何时刻,我们都可以通过发送一个重置报文段替代FIN来终止一条连接。这种方式也被称为终止释放


终止一条连接为应用程序提供两大特性:

  • 任何排队的数据都将被发送出去,一个重置报文段会被立即发送出去
  • 重置报文段的接收方会说明通信另一端采用可终止的方法而不是一次正常的关闭。

需要注意:

重置报文段不会被通信另外一端做出任何响应,即它不会被确认。接收重置报文段的另一段会终止连接并通知应用程序当前连接已被重置。

半开连接

如果在未告知另一端的情况下通信的一端关闭或者终止连接,那么就认为该TCP连接处于半开状态。这种情况一般发生在通信一方的主机崩溃。只要不尝试通过半开连接传输数据,正常工作的一端不会检测另一端已经崩溃。产生半开连接的另外一个共同原因是某台主机的电源被切断而非正常关机。

时间等待错误

设计TIME_WAIT状态的目的是允许任何受制于一条关闭连接的数据报被丢弃。在这段期间,等待TCP通常不需要做任何操作,它只需要维持当前状态直到2MSL的计时结束。然而,如果它在这段时间内收到任何关于这条连接的一些报文段,或者是更加特殊的重置报文,它将被破坏。这种情况被称为时间等待错误(TIME-WAIT Assaaination TWA RFC[1337])

为解决这个问题,许多系统规定当处于TIME-WAIT状态时不对重置报文做出反应。

【TCP】连接管理的更多相关文章

  1. TCP连接管理(TCP Connection Management)

    在最近的求职面试过程中,关于"建立TCP连接的三次握手"不止一次被问到了,虽然我以前用同样的问题面试过别人,但感觉还是不能给面试官一个很清晰的回答.本文算是对整个TCP连接管理做一 ...

  2. TCP系列07—连接管理—6、TCP连接管理的状态机

            经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...

  3. tcp连接管理

    [root@ok etc]# cat /proc/sys/net/core/netdev_max_backlog 每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目 ...

  4. TCP/IP 笔记 - TCP连接管理

    TCP是一种面向连接的单播协议,在发送数据之前,通信双方必须在彼此建立一条连接:这与UDP的无连接不同,UDP无需通信双方发送数据之前建立连接.所有TCP需要处理多种TCP状态时需要面对的问题,比如连 ...

  5. 多图详解 TCP 连接管理,太全了!!!

    TCP 是一种面向连接的单播协议,在 TCP 中,并不存在多播.广播的这种行为,因为 TCP 报文段中能明确发送方和接受方的 IP 地址. 在发送数据前,相互通信的双方(即发送方和接受方)需要建立一条 ...

  6. NIO 服务端TCP连接管理的方案

    最近做的一个项目需要在服务端对连接端进行管理,故将方案记录于此. 方案实现的结果与背景 因为服务端与客户端实现的是长连接,所以需要对客户端的连接情况进行监控,防止无效连接占用资源. 完成类似于心跳的接 ...

  7. TCP 连接管理

    实验代码和内容:https://github.com/ZCplayground/Understanding-Unix-Linux-Programming/tree/master/11.socket 明 ...

  8. TCP拥塞控制及连接管理

    在阅读此篇之前,博主强烈建议先看看TCP可靠传输及流量控制. 一.TCP拥塞控制 在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞(congestion ...

  9. TCP系列02—连接管理—1、三次握手与四次挥手

    一.TCP连接管理概述 正如我们在之前所说TCP是一个面向连接的通信协议,因此在进行数据传输前一般需要先建立连接(TFO除外),因此我们首先来介绍TCP的连接管理. 通常一次完整的TCP数据传输一般包 ...

随机推荐

  1. arduino系列文章

    arduino系列文章 1.Arduino基础入门篇-进入Arduino的世界 2.关于使用Arduino做开发的理解 3.详解Arduino Uno开发板的引脚分配图及定义(重要且基础) 4.Ard ...

  2. .net 结合FFMPEG

    读取流 https://blog.csdn.net/vanjoge/article/details/79657874 基于设备,推流 https://blog.csdn.net/lxbwolf/art ...

  3. centos7yum的配置

    首先呢,本人的centos的版本是7.5 这里我主要介绍的是通过挂在系统镜像文件和指定网络epel镜像源. 首先指定本地的光盘当做yum的仓库 1.删除/etc/yum.repos.d的所有文件 2. ...

  4. Ckeditor5显示css样式

    Ckeditor5在编辑模式是通过js加载样式的,但是在显示时没有提供,官方提供了两种方式来实现. https://ckeditor.com/docs/ckeditor5/latest/builds/ ...

  5. hadoop(二MapReduce)

    hadoop(二MapReduce) 介绍 MapReduce:其实就是把数据分开处理后再将数据合在一起. Map负责“分”,即把复杂的任务分解为若干个“简单的任务”来并行处理.可以进行拆分的前提是这 ...

  6. 【AtCoder】ARC059

    为啥这场ARC那么水--一个点就切完了 ARC059 C - いっしょ / Be Together 枚举就行 #include <bits/stdc++.h> #define fi fir ...

  7. 剑指offer32:把数组排成最小的数

    1 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 2 思路 ...

  8. PHP搭建B2C分销商城系统需要考虑哪些因素?(一)

    在网购日渐繁盛的今天,传统线下门店和代理分销越发显示出其弊端.此种情况下,进入互联网市场是最好的选择.入驻第三方平台成本太高,无法掌握自己的流量,所以搭建自己的分销平台成为众多企业的首选.搭建B2C分 ...

  9. fiddler笔记:与Web Session的交互

    Decode Selected Session 解决响应体显示乱码的问题. AutoScroll Session List 决定Fiddler是否会自动将新增的Session添加到web sessio ...

  10. Python 【函数】

    函数 内置函数print() input() len() type() ... print('Hello World') 函数 参数 定义函数def greet(name): print(name+' ...