传输层 TCP连接管理 建立TCP连接/状态/变迁

TCP是面向连接的协议,所以使用TCP的时候要先建立连接,建立连接是通过三次握手来实现的。

 

 

三次握手的目标


同步 Sequence 序列号

  • 初始序列号 ISN(Initial Sequence Number)
服务器端和客户端之间的所使用的seq都是不同的,所以在握手当中的三次都要分别交换这个isn。
交换 TCP 通讯参数
  • 如 MSS(最大报文段)、窗口比例因子(想扩大滑动窗口的时候)、选择性确认(更有效的重传丢失的报文)、指定校验和算法

三次握手


client首先将它的ins发给server,server收到syn之后,它要回一个ack,server也要发自己的ins让客户端知道我的序列号在哪,当然客户端也要回一个ack。

第二步可以将syn/ack放在一个报文当中,一次性的发给client。

上面就是三次握手,三次握手当中使用了syn,就是同步的意思,也使用了ack确认。

 -c只抓取3个包,因为3个包正好是前面的3次握手,-S用绝对序列号替换相对序列号。

这里client传输

了它的isn,seq 1676510846,给到了server,server会回加1,ack 1676510847,client收到这个报文之后就知道server确认了,同时server也发送了自己的isn,seq 715862251,client通过最后一个ack通过对seq 715862251确认+1,那么就是3次握手。

这个isn seq是随机的,每次都是不同的。

三次握手(1):SYN 报文


 syn要在标记位的第七位置为1,那么就代表这个一个syn报文。在seq当中填入我们的序列号码,也就是我们的isn。

三次握手(2): SYN/ACK 报文 


在第二个报文当中其实就是ack+syn,这里面重点关注4个地方。

序列号,也就是server中使用的isn,确认号码就是我收到client的isn+1,为了让确认号码有效,我要在flag当中第四位ACK置为1,第七位SYN置为1。

三次握手(3): ACK 报文  


 最后一个ACK报文在ACK位置置为1,让确认号码有效。

TCP的连接建立


应用程序在通信的时候,也即是进程在通信的时候,浏览器访问web站点,HTTP协议要想发送的话,我这个计算机要先去调用TCP协议,先建立连接,发送tcp建立连接的请求,服务端给我一个确认,我再给服务器一个确认。需要发三个数据包。

建立了TCP连接之后,再发送http的报文,web站点再用这个连接将网页返回给我的客户端。

当所有的通信都结束了,那么浏览器还要释放连接。

tcp在通信之前需要发送3个数据包来建立连接,释放连接需要发送4个数据包。

之前说的可靠传输,流量控制,拥塞避免,这些都是在通信过程当中用到的技术。

建立连接要3次握手,两次握手行不行呢?

客户端要访问服务器的话,客户端向服务端发起建立tcp连接的请求,请求的时候带着一些参数,接受窗口是多少,最大报文段是多少,是不是支持选择性确认,在建立连接请求的时候就带着这些信息。

web服务器收到之后给它一个确认,我的接受窗口是多少,我的报文段最大支持多少,是不是支持选择性确认,将这些参数告诉客户端。

这一次请求,一次确认不就ok了吗?为啥还要求客户端再给服务器再发一个确认。

这里考虑了一种特殊的情况,客户端发送了一个请求,这个请求走的路比较远,这是第一个请求,客户端等了一下发送的请求没有响应,有没有收到确认?于是再发送了一个,这是第二个请求,第二个请求比第一个请求先到,第一个还没到第二个就先到了。

然后web服务器给第二个发了一个确认,然后第一个才到,客户端认为第一个请求作废了,因为没有响应才发送了第二个。

然后web服务器收到了第一个请求之后,它给这个请求发送一个确认,结果客户端一看这是无效的确认,第一个早失效了你给我发确认有啥用?于是就不搭理它了,但是web服务器不知道这个事情,它认为客户端发送了两个建立连接的请求,web服务器这边就会消耗资源。

如果tcp规定了三次握手,web服务器给你发送了确认之后,在一个规定的时间里面没有等到你这个确认,那么web服务器就将这个释放了。

3次握手是为了避免web服务器一直等着客户端的连接,但是客户端不搭理它,为了避免这种情况需要3次握手。



为什么两次握手不可以呢?


为了防止已经失效的连接请求报文段突然又传送到了 B,因而产生错误。比如下面这种情况:A 发出的第一个连接请求报文段并没有丢失,而是在网路结点长时间滞留了,以致于延误到连接释放以后的某个时间段才到达 B。本来这是一个早已失效的报文段。但是 B 收到此失效的链接请求报文段后,就误认为 A 又发出一次新的连接请求。于是就向 A 发出确认报文段,同意建立连接。

对于上面这种情况,如果不进行第三次握手,B 发出确认后就认为新的运输连接已经建立了,并一直等待 A 发来数据。B 的许多资源就这样白白浪费了。

如果采用了三次握手,由于 A 实际上并没有发出建立连接请求,所以不会理睬 B 的确认,也不会向 B 发送数据。B 由于收不到确认,就知道 A 并没有要求建立连接。 

TCP的连接建立

 客户端和服务端建立TCP连接的时候,这样的数据包是不带数据的,然后它还有个特点,SYN叫做同步标记位,syn这个标记位为1,ack为确认,确认为0说明,说明tcp首部确认的字段是无效的。

确认通常就是告诉对方收到了第多少个数据包,你该发多少个数据包,因为客户端从来没有收到服务器这边的数据包,所以这个确认号就没有意义,所以这个标记位为0。

参数可以看到最大传输报文段mss 1460。

允许选择性确认。

接受窗口是64240。

上面tcp建立请求包含了上面这些信息,接受窗口是多大,最大报文是多大,是不是支持选择性确认。

上面是首部+选项部分,没有数据部分。

上面是建立连接的请求。

建立TCP连接确认

 ack syn标记位为1,说明ack确认标记位起作用了,说明确认字段有意义,可以看到序号为0,确认号为1,告诉客户端1以前的字节都收到了。

下面是服务器的参数。

确认的确认

 这是第三个包,ack标志位为1,syn标记位为0了,也就是说只有前面两个数据包请求和确认的syn标记位才为1。

TCP三次握手


 来看看客户端和服务端状态。

一开始客户端这里tcp连接是close的,发一个建立tcp连接的请求,syn标记位为1,ack标记位为0,序号是客户端随机给的。

服务器收到之后是listen状态,监听客户端的请求,之后变为syn received状态,之后给客户端发送确认,标记位都为1,y是服务器设定的一个序号,比较大的随机数,确认号为x+1,告诉客户端x收到了,你该发x+1个字节了。

客户端收到确认之后状态为establish建立连接。

之后客户端再给它发确认的确认,ACK大写的代表标记位,小写的代表序号和确认号。

当执行三次握手的时候,客户端和服务器关于这条连接的状态都在发生变迁,当理解了tcp状态是如何变迁的时候,就能够更有效的定位一些复杂的网络问题。 

下面是三次握手当中所涉及的5种状态,

最初大家都是close的状态,其中服务器需要监听80 443等端口,所以处于listen状态,在三次握手完成之后,大家都需要进入establish的状态,对于状态怎么查看呢,使用netstat工具来查看。

[root@master networking]# netstat -anp | grep tcp
tcp        0      0 169.254.25.10:9254      0.0.0.0:*               LISTEN       4505/kube-proxy     
tcp        0      0 192.168.111.6:2379      0.0.0.0:*               LISTEN      1781/etcd           
tcp        0      0 127.0.0.1:2379          0.0.0.0:*               LISTEN      1781/etcd           
tcp        0      0 192.168.111.6:2380      0.0.0.0:*               LISTEN      1781/etcd           
tcp        0      0 0.0.0.0:31759           0.0.0.0:*               LISTEN      4505/kube-proxy     
   1091/master         
tcp        0      0 169.254.25.10:50542     169.254.25.10:9254      TIME_WAIT   -                   
tcp        0      0 192.168.111.6:2379      192.168.111.6:50166     ESTABLISHED 1781/etcd           
tcp        0      0 169.254.25.10:50642     169.254.25.10:9254      TIME_WAIT   -                   
tcp        0      0 192.168.111.6:49878     192.168.111.6:2379      ESTABLISHED 2595/kube-apiserver 
tcp        0      0 192.168.111.6:50118     192.168.111.6:2379      ESTABLISHED 

 可以看到有listen的状态,有establish的状态,在介绍4次握手关闭的时候,往往会看到大量time_wait状态。

回过头来看三次握手的状态变迁,首先客户端发起了syn,客户端立刻就会进入syn-sent的状态,在netstat当中很难看到这个状态,因为当我们收到syn+ack之后我们就会从syn-sent进入到establish状态了,这个过程可能非常当能只有几百毫秒,所以很难观察到这样一个状态。

当服务器收到syn之后,它会进入syn-received的状态,这个状态会一直延续下去,直到客户端返回ack,那么也会进入establish状态。

从syn-send和syn-received可以很清楚的看到,就是看这个syn有没有发,还是说我收到了,以此来命名的。

有些攻击者就会不使用操作系统内核提供的tcp栈,而是自己简单的构造出来syn的帧,发给了server之后,它却不发ack,使得大量的连接都处于syn-received的状态,以至于占用了server太多的资源,使得正常的连接无法正常的建立,这就是syn的一种攻击方式。

两端同时发送SYN:双方使用固定源端口且同时建连接

TCB: Transmission Control Block,保存连接使用的源端口、目的端口、目的 ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp 状态、tcp 输入/输出队列、应用层输出队列、tcp 的重传有关变量等(保存连接当中使用的各种状态信息,比如我的端口和对方的端口,等)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值