TCP与UDP协议

TCP协议头部解析
在这里插入图片描述
TCP端口
  TCP的全称是Transmission Control Protocol,即传输控制协议。它在RFC 793中被定义。所有TCP通信都使用源端口和目的端口,这些信息可以在每个TCP数据包的头部找到。而为了能够将数据传输到远程服务器或设备的特定应用中去,TCP数据包必须知道远程服务器所监听的端口。如果想要尝试一个不同于所设置的端口,呢么这个通信就会失败。一般来说,TCP通信中的源端口并不重要,可以随机选择。而在使用TCP通信的时候,我们一共可以使用65535个端口。图例:
在这里插入图片描述
  我们看第一个数据包的TCP头部。可以看到这个数据包是从IP地址为192.168.0.9发往192.168.0.8的,它的源端口是57128,属于源端口,它是有操作系统选取的。目的端口是80端口,这是一个标准端口,这个端口通常提供给使用HTTP的Web服务器。其中Wireshark自身会维护一个端口列表,记录这些端口关联的常用服务,我们可以选择菜单栏的"Edit"->“Preference”->“Name Resolution”,勾选"Resolve transport names",这就可以打开传输端口解析。但是有些时候开始解析可能会对我们的分析造成困扰,因此要根据实际情况使用。
第二个数据包是从IP地址为92.168.0.8发往192.168.0.9的,除了IP地址相反之外,源端口和目标端口也是相反的。事实上,所有基于TCP的通信都以相同的方式工作:选择一个随机端口与一个已知的目标端口进行通信。在发出数据包之后,远程设备就会与源设备使用建立起的端口进行通信。

TCP的三次握手:
  由于TCP提供的是可靠的数据传输,因此在传输之前,需要与目标主机建立连接。而所有基于TCP的通信都需要以两台主机之间的握手开始,握手过程如下图
在这里插入图片描述
上图中的seq表示的是请求的序列号,ack表示确认序列号,SYN和ACK为控制位。

  1. 在第一次握手建立连接时,客户端会向服务器发送SYN数据包(SYN=1,seq=x),并进入SYN_SENT状态,等待服务器的确认。
  2. 第二次握手其实是分为两步来完成的,即SYN加上ACK,也就是请求和确认数据包。(1)服务器收到客户端请求,想客户端回复一个确认信息(ack=x+1).(2)服务器再想客户端发送一个SYN包(seq=y)从而建立连接请求,此时服务器进入SYN_RECV状态。
  3. 第三次握手时客户端收到服务器的回复,也就是SYN加上ACK数据包。此时,客户端也要向服务器发送确认数据包(ACK)。发送完毕后,客户端和服务器就进入了ESTABLISHED的状态,从而完成了三次握手。那么接下来,客户端和服务器就可以开始传输数据了。
      需要说明的是,Wireshark为了让我们分析更加简便,引入了一个新的特性,可以自动将TCP数据包的序列号替换为相对值。但是这里我们不需要这个功能,我们希望看到原始值,可以选择菜单栏的“Edit”->“Preference”,展开窗口左侧的“Protocols”并选择“TCP”,然后取消勾选“Analyze TCP sequence numbers”,再单击OK即可。

TCP四次挥手断开
在这里插入图片描述

  1. 客户端向服务器发送一个设置了FIN和ACK的数据包,告诉服务器通信完成。
  2. 服务器收到客户端发来的数据包后,发送一个ACK数据包来回应客户端。
  3. 服务器再向客户端传输一个自己的FIN/ACK数据包。
  4. 客户端收到服务器的FIN/ACK数据包后,再向服务器发送一个ACK数据包,之后就结束通信过程。
    在这里插入图片描述
    上图为一个TCP通信的挥手断开过程,其中第二个数据包为"捎带"数据包,也就是在四次挥手断开的第二次和第三次合并了。

TCP的重置
  正常情况下,TCP通信的连接都会以TCP的四次握手断开。但在现实中,网络有时会出现断掉的情况。这就有可能遭受到了网络攻击,也有可能是出现了配置错误的情况。此时就需要使用设置了RST标志的TCP数据包,表示出现了连接被异常终止或拒绝连接的请求。如下图:
在这里插入图片描述
上图第一个数据包是从192.168.0.9发出,并尝试与192.168.0.8的1234端口建立连接,但是由于目标主句并没有开启1234端口,因此在第二个数据包中,就回应了一个RST数据包,告诉源主机1234端口无法建立连接,那么通信也就终止了。由此可见,RST数据包可以在通信序列的开始或者在主机通信的过程中,将通信终止。

TCP数据传输
 TCP提供有序的数据传输,因此每个数据段都要标上一个序列号,也就是Seq的值,这样当接收方收到乱序的数据包时,就可以根据这个序列号进行重新排序了。这里我们并不需要知道Seq的起始值是怎么计算的,但是必须要理解这个值的增长方式。 在TCP连接中,因为双方都可以是接收方,所以他们各自除了会维护各自的Seq值以外,还会维护各自的Ack的值。
 如果数据包出现了乱序的情况,那么接收方只要依据Seq的值从小到大进行排列就可以了,这样就保证了数据传输的有序性。或者当出现了丢包的情况,接收方只要通过前一个Seq+Len的值再减去下一个Seq的差,就可以判断丢了哪些包。

TCP窗口
  在TCP协议中,实现了滑动窗口的机制,可以用来检测什么时候发生了数据包的丢失,并且调整数据的传输速率以避免丢失情况的加剧。滑动窗口机制利用数据接收方的接收窗口来对数据流进行控制。几首窗口是数据接收方自己依据实际情况而定下来的值,保存在TCP的头部信息中。这个值告诉了发送方自己希望在TCP缓冲空间中保存多少数据。这个缓冲空间是数据在可以向上传递到等待处理数据的应用层协议之前的临时存储空间。所以,发送方一次只可以发送Window Size所指定的数据量。而为了传输更多的数据,接收方必须要发送确认数据包,表示之前的数据已经接收到了。同时也必须要处理占用着TCP缓冲区的数据,从而清空缓冲区,以接收新的数据。
  有些情况下。服务器可能无法处理客户端发送的数据,比如服务器出现故障等的情况,此时仅仅减小窗口的大小是不行的,而需要将接收窗口的值直接设置为零值。也就是通过ACK数据包告诉客户端,窗口的大小是0,让客户端停止所有的数据传输,但是仍然会通过"保活数据包"来保持与服务器的连接。客户端会周期性地发送这样的数据包,以检测服务器的接收窗口的状态。一旦服务器排除了故障,能够再次处理数据,那么就会向客户端发送一个非零的窗口大小以恢复通信。

MSS最大报文段长度
  MSS值是收发双方协商通信时每一个报文段最大能承受的数据长度。MSS值作用是为了避免在网络层出现IP分片的情况,分片和重组的过程必然会对性能产生影响,而且任何一个分片出现错误或者丢失都会导致整个分组被丢弃,意味着整个报文段需要重传,严重影响性能。
  MSS值通过MSS选项商定,MSSS选项在TCP三次握手中,每一方都会通告它期望的MSS选项,如果一方不接收另一方的MSS,则MSS默认为536个字节。
  MTU:最大传输单元 1500字节
  MSS:通常为MTU-20字节(IP头部)-20字节(TCP头部)

TCP重传原理
  在TCP重传思维理论中,重传计数器是用于决定是否有必要进行数据包重传的一个主要机制。重传计时器维护者一个叫做重传超时(Retransmission timeout,RTO)的值。在使用TCP进行数据包的传送时,重传计时器就会被启动。当收到数据包的ACK,也就是确认数据包时,计时器就会停止。从发送数据包到接收数据包的时间,被称作往返时间(Round-trip time,RTT)。我们将若干个往返时间求和并计算平均值,就可以得出最终的RTO值。
  但在最终计算出RTO值之前,数据的传输操作将会一直依赖于默认的RTT值。这个设置用于主机之间的初始通信,并基于接收到的数据包的RTT进行调整,从而形成真正的RTO值。一旦RTO值被确定下来,重传计时器就被应用于每个传输的数据包,从而确定数据包是否丢失
  当数据包发送出去,但是接收方没有发送TCP ACK数据包时,发送方就假设原来发送的数据包并没有发送到目标主机,认为它丢失了,于是就进行重传。重传之后,RTO的值翻倍;如果在到达极限值之前依旧没有收到ACK数据包,那么就会进行第二次重传,如果还是没有收到ACK,那么RTO的值就会再次翻倍。那么每次的重传,都会导致RTO的值翻倍,直到收到ACK数据包,或者发送方达到配置的最大重传次数为止。当然这里所说的每次翻倍,只是比喻,实际上在计算RTO的时候,是需要几个公式的。一般来说,Windows操作系统会重传5次,而Linux则为15次。这个次数是可以进行修改的。

TCP的快速重传
  如果接收方收到了乱序的数据包,就发送重复的TCP ACK数据包。TCP在其头部使用序列号和确认字段,以确保数据被可靠接收并以发送的顺序进行重组。Seq序列号可以帮助数据进行有序的传输。如果接收方遇到不符合顺序的序列号,就知道数据包丢失了。那么为了正确地重组数据,接收方必须要得到丢失的数据包,因此接收方会发送一个包含丢失数据包序列的ACK数据包,这样发送方就可以知道应该发送哪一个数据包了
  如果发送方收到3个来自接收方的重复ACK时,发送方就会假设这个数据包确实在传输的过程中丢失了,于是就立刻发起快速重传机制。一旦触发了快速重传,其它所有正在传输的数据包都要先暂停发送,知道把丢失的数据包发送出去为止。为什么要规定凑满三个重复ACK数据包呢?因为网络数据包有些时候在传输的过程中会出现乱序的情况,乱序的数据包一样会触发重复ACK数据包,但是由于出现乱序而重传没有必要。由于一般的乱序的距离不会相差太大,所以限定成3个或者以上,就可以很大程度上避免由于乱序而导致的快速重传。

多个数据包丢失的情况
  假设发送方一共发送了8个数据包,但是其中的2号和3号数据包丢失了,而1、4、5、6、7、8号数据包都抵达了接收方,并且触发了Ack 2,也就是通知发送方,没收到2号数据包。对于发送方来说,只能通过Ack 2知道2号数据包丢失了,但是并不知道还有哪些数据包丢失了。那么在重传了2号数据包之后,接下来应该传哪一个呢?有以下三种方案: 方案1:把3、4、5、6、7、8号数据包重传一次。这是最简单直接的办法,但是这个丢包的后果导致了多个数据包被重传,效率是非常低的。其实早期的TCP协议就是这样处理的。 方案2:接收方收到重传过来的2号包之后,会回复一个Ack 3,这样发送方就可以知道3号数据包也丢失了,于是传送3号包。这样当接收方收到重新传送过来的3号包之后,由于所有的数据包都收到了,就回复一个Ack 9,那么发送方就可以从9号数据包开始发送数据了。这个方案被称为NewReno,在RFC2582和RFC3782中被定义。NewReno的方法虽然说比较完善,但是在丢包量很大的时候,就需要花费多个往返时间来重传所有丢失的数据包。 方案3:接收方在请求重传2号包的时候,顺便把收到的数据包号告诉发送方。所以网络上数据的传输过程因该是这样的: 在收到4号数据包时,告诉发送方已经收到4号,但是2号没收到。 在收到5号数据包时,告诉发送方已经收到4、5号,但是2号没收到…… 这样一来,发送方就可以对丢包的细节了如指掌,在快速重传了2号数据包之后,它可以接着传3号,然后再传9号数据包。这种方案被称为SACK,在RFC2018中被定义。

UDP数据包分析
  UDP指的是User Datagram Protocol,即用户数据报协议,是在现代网络中最常使用的另外一种第四层的协议。如果说TCP是为了满足带有内在错误检测的可靠数据传输,那么UDP主要是为了提供高速的传输。出于这个原因,UDO是一种尽力服务,通常会被称为无连接协议。一个无连接协议并不会正式的建立和结束主机之间的连接,也不会像TCP那样存在握手和终止的过程。无连接协议意味着它是一种不可靠的服务,这将使得UDP的流量一点也不稳定。但依赖于UDP的协议通常都会有其它的可靠服务,或者使用ICMP的一些功能来保证连接更可靠一些。比如,应用层协议DNS和DHCP需要高度依赖数据包在网路上的传输速度,因此需要使用UDP协议,并利用他们自身的错误检查以及重传计时来保证数据的正确传输。
  而UDP的内容也很简单,包含有源端口、目标端口、数据报的长度以及校验和等信息。需要强调的是,UDP并不关心传输的可靠性,所以任何使用UDP的应用在必要的时候都需要采取特殊的步骤,从而保证传输的可靠性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值