Linux--深入解析TCP协议

在谈TCP协议之前,我们有必要先了解UDP协议,UDP协议与TCP协议一样,都是属于传输层协议,那么我们就来看看他们之间有什么区别:

  1. 可靠传输vs不可靠传输:TCP传输属于可靠性传输,那么它就一定会有许多机制来保证传输的可靠性,即需要的开销就更多;而UDP协议不保证可靠,并不是说它传输的数据有错误它也不会去管,而是通过16位校验和检测数据是否出错,如果有错,就会直接丢掉。但是,并不会返回任何错误信息。
  2. 面向连接vs无连接:面向连接也是属于TCP协议保证可靠性的机制的一种。UDP协议则是无连接,在知道对方的IP地址和端口号后,直接将数据发送给对方。
  3. 面向字节流vs面向数据报:这都是站在应用层的角度来谈的,因为TCP有一系列机制来保证数据的按序到达,所以另一端接收到数据后会按序放到TCP的接收缓冲区,应用层在可以随意读取。而UDP并没有这种机制,所以,发送端一次发送多大的数据,接收端也要一次读完,这就是面向数据报。

UPD协议端格式:
这里写图片描述

字段解释:

  1. 16位源端口号:标识“自己”在这个主机使用的端口号
  2. 16位目的端口号:标识将来到对方后“我”要将数据交给上一层的“谁”, 因为应用层的协议太多,不能穷举,所以这里只要标识出哪一个进程就好了。
  3. 16位UDP长度:表示整个数据报(UDP首部+UDP数据)的最大长度(64K)
  4. 16位校验和:为了验证数据是否出错,如果出错,就会直接丢弃,不会通知应用层。

这里只是大致的介绍了UDP协议的内容,重头戏是TCP协议,在了解TCP协议之前,先来看看TCP协议段格式:
这里写图片描述
是不是发现要比UDP协议的报头信息复杂的多,这就是TCP为什么能保证传输的可靠性。下面我们来一个一个介绍这些字段的作用。

  1. 16位源端口号与16位目的端口号的作用与UDP中的一样,表示从哪个进程来到哪个进程去。
  2. 32位序号和32位序号:在了解这两个字段之前,首先要知道,TCP协议在传输数据时,将每个字节的数据都进行了编号,即序列号,在发送数据时,会将此次数据的最大序列号填到32序号字段中,接收端在接收到数据后,将这些数据按序放到接收缓冲区当中,然后,将最大序列号+1填到确认序号字段当中发给对方,表示确认序号(假设位1001)之前的数据“我”都接收到了,下次应该发送序列号比确认序号(1001)大的数据了。
  3. 4位首部长度:TCP首部长度最大15*4(字节)=60字节,其中标准长度为20字节(不包含选项)
  4. 6位保留位:这里不多作介绍。
  5. 6位标志位:
    1. URG:紧急指针标志位 ,表示紧急指针是否有效
    2. ACK:确认标志位,表示确认序号是否有效。
    3. PSH:提示接收端的应用程序立刻从TCP缓冲区中把数据拿走。
    4. RST:重置标志位,表示对方要求重新建立连接。把携带该标志位的称为复位报文段
    5. SYN:同步标志位,表示对方请求建立连接,把携带标志位的称为同步报文段。
    6. FIN:结束标志位,通知对方“我”要关闭了,把携带该标志位的称为结束报文段。

6.16位窗口大小:我们都知道,TCP是有自己的缓冲区的,当发送端发送数据过快而接收端处理数据太慢时,接收端的TCP缓冲区中的数据就会越来越多,当达到缓冲区所能保存数据的最大值时,这时,如果发送端继续发送数据,就可能会造成数据的丢失,但是,我们要时时刻刻记住,TCP协议是保证可靠的,所以是不会允许这种事情发生的,16位窗口大小就是为了防止这样的事情发生的,它是用来描述自己当前接收能力(接收缓冲区大小)的字段。
7.16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的校验和不光包含TCP的首部,还包含数据部分。
8.16位紧急指针:标识哪部分数据是紧急数据,因为TCP有字节序,所以它支持优先访问某一部分数据。
9.40位的选项:这里不多做解释。

介绍完TCP协议段的格式后,我们再来看看TCP都有哪些机制来保证它的可靠性。

1.校验和:就是最基础的保证数据不会出错,这里不多做介绍。
2.序列号:序列号保证了数据按序到达,如果有重复数据还能用来去重。这都是用可靠性的一种。
3. 确认应答(ACK)机制:就是我们在上面介绍的序号和确认序号,我给你发送一段数据(字节序1-1000),你就要填充你的ACK标记位以及确认序号(确认序号填充1001),用来表示数据你已经收到了,下次要发就从字节序为1001的数据发送。
4. 超时重传机制:假设A为发送端,B为接收端,A给B发送一组数据,有两种情况,A会认为数据B没收到,第一种是A给B发送的数据包丢了,第二种就是数据B收到了,但是B再给A发送确认应答时,确认应答丢了,这两种情况都是发送端发送数据后,如果在特定的时间内没有收到对方的确认应答,都会认为对方没有收到数据,进而将之前发送的数据进行重发。这种机制就是超时重传机制,也是TCP保证可靠性的一种。
5.流量控制:TCP支持根据接收端的处理能力,来决定发送数据的速度,这种机制就叫做流量控制。之前我们讲过,窗口大小就是用来描述自己当前的接收能力(处理能力)的,而发送端就是根据这个字段来控制发送速度。
6.拥塞控制:由于在网络上传输数据的计算机有成千上万个,可能现在网络已经非常堵塞,如果一次我们一次发送大量数据,不仅会造成网络更加堵塞,还有可能会造成丢包的问题,当然,丢包了,可以触发超时重传,但是如果大量的丢包呢?所以这里TCP就引入了慢启动机制,也引入了一个新概念,拥塞窗口,发送刚开始的时候,定义拥塞窗口大小为1,每收到一个ACK应答,窗口大小+1,每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小值作为实际发送的窗口(数据大小);拥塞窗口大小的增长速度是指数级别的,把这种增长机制叫做“慢启动机”制。

看完这些TCP用来保证可靠性的机制之后,我们再来看看它最重要的一种保证可靠性的机制之一,面向连接(连接管理机制)
正常情况下,TCP要经过3次握手建立连接,4次挥手断开连接。
三次握手:
要通信时,都是要有一方主动,正常情况下,主动的一方都为客户端,服务器一直处于监听状态,当客户端调用connect,表示请求连接,此时,客户端先会给服务器发送携带SYN同步标志位的同步报文段,当服务器收到之后,会发送携带ACK+SYN标志位的报文,表示请求已经收到,同意建立连接,当客户端收到后,会再向服务器发送ACK确认应答,connect返回,此时客户端认为连接已经建立成功,当服务器收到客户端发送的ACK后,认为连接建立成功。
三次握手,问什么是三次握手呢?大家肯定想过,为什么是三次,不是四次、一次、两次,一次握手就相当于没握手,三次握手都已经可以解决问题了,所以不用四次,那为什么不是两次呢?因为两次握手有致命的短板!因为通常情况下,客户端都是主动建立连接的那一方,如果是两次握手,假设最后一次报文丢了,服务器还是会认为连接已经建立成功,要知道,维护这些连接也是需要成本的,如果有恶意软件攻击服务器,只发送SYN请求连接,不接收服务器发来的ACK+SYN,那么服务器就会认为每一个连接都已经建立成功了,都会维护起来,最后可能会因为开销太大而崩溃。
四次挥手:
在建立连接需要有“人”主动,对方只要同意就可以,但是断开连接就不一样了,不仅需要一方主动,在对方同意断开连接之后,对方也要跟“我”断开连接,就像男女朋友分手一样,你跟我提出分手后,我同意了,这时,你认为我已经不是你对象了,但是,我还不这样认为,我必须也要跟你提出分手,你再同意,此时,我才认为你也不是我对象;这时,才是真的分手了。接下来我们看看详细过程。
在TCP断开连接时,一方(假设为客户端)会调用close(fd)关闭连接,即发送携带FIN标志位的结束报文段,表示想要断开连接,当服务器收到后,会发送ACK确认应答,表示我已经收到并且同意;之后,服务器也会调用close(fd),即也会发送携带FIN标志位的结束报文段,表示“我”也要跟你断开连接,当客户端收到之后,会发送ACK表示收到并且同意断开连接,此时客户端(主动断开连接的一方)处于TIME_WAIT状态,当服务器收到后,就“真的”断开连接,处于CLOSED状态。TIME_WAIT(时间长度为2MSL)过后,客户端也会“真的”断开连接,处于CLOSED状态。四次挥手完毕!
TIME_WAIT:等待2倍的报文最大生存时间,为了确保最后一次报文是否被收到。

这里写图片描述
TCP协议之所以应用广泛的原因不仅仅时因为它保证了可靠性而是在这基础之上还尽量保证性能,接下来我们就来看看TCP为了提高性能而建立的机制。
1.滑动窗口:之前在讲确认应答的时候说,“你”给“我”发送一个数据包(序列号为1~1000),我再给你发送一个ACK确认应答(确认序号1001)表示数据我都收到了,下次该从什么地方发,这样是可以保证传输的可靠性,但是每发一个数据包都要对应的发一个确认应答,这样太麻烦了,而且还会影响性能,为了提高性能,就提出了一个新的概念,窗口大小,窗口大小指的是无需等待确认应答而可以继续发送数据的最大值(就是由接收端当前的接收缓冲区大小决定),这样在发送数据的时候,一次就可以发送一个窗口大小(由很多数据包)的数据(先不考虑拥塞窗口),而不用向之前那样,发一个,等收到确认应答之后才能发下一个,这样发送后,等到收到第一个包的ACK后,滑动窗口就会后移“一个”,以此类推,操作系统为了维护滑动窗口,需要开辟发送缓冲区来记录当前还有那些数据没有应答,只有确认应答过的数据才能从缓冲区删除。窗口越大,网络吞吐率就越高。
但是如果丢包了呢?
在发送端开来,有两种情况它会认为是包丢了,一种是数据包接收端收到了,但是接收端给发送的ACK丢了,这种情况其实不影响,因为我们一次发送多个数据包,某一个包的ACK丢了,还会收到其他后序包的ACK,这样也能确认接收端已经收到数据;但是,还有一种情况是数据包丢了,如果是这种情况,就可能会触发另一种保证性能的机制–快重传机制
2.高速重发控制(快重传):
这里写图片描述
3.延迟应答:延迟应答就是字面上的意思,过一会再应答,因为每次确认应答的时候我们都要在16窗口的字段上填上自己接收缓冲区的大小,如果在收到数据包时立刻就应答的话,这样应用层还“来不及”从接收缓冲区中拿走数据,返回的窗口大小会比较小,但是如果“过一会”再应答,这样窗口大小可能就会大很多。因为窗口越大,网络吞吐量就越大,传输效率就越高。但是要注意,不是所有的数据包都可以延迟应答,“一会儿”(延迟的时间)不同操作系统不一样。
4.捎带应答:因为每次如果只是为了应答就发一个数据包给对方,这样就太浪费资源了,在实际情况当中,大多数服务器与客户端之间都是“一发一收”,服务器不仅仅只是发送数据,客户端也不会只收收据,所以确认应答的时候,ACK就可以搭顺风车,和想要发送的数据包一起发送给对方。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值