【Java网络编程】IP网络协议与TCP、UDP网络传输层协议

1.1、IP协议

当应用层的数据被封装后,想要将数据在网络上传输,数据究竟要被发往何处,又该如何精准的在网络上定位目标机器,此时起到关键作用的就是"IP协议"。
IP协议的作用在于把各种数据包准确无误的传递给目标方,其中两个重要的条件是IP地址和MAC地址。其中IP地址就是所有主机在网络通信中的唯一标识,但由于IP地址是稀有资源,不可能每个主机都拥有一个IP地址,因此路由器里面会记录我们主机的MAC地址,通常的IP地址是路由器根据MAC地址生成的,而MAC地址是全球唯一的。

举例:IP地址就如同是物流线路上的驿站地址,而MAC地址就是具体货架上货物的位置。

之前的IP地址采用的IPv4格式,目前大部分主机都已向IPv6过渡。

1.1.1、IP地址的组成与分类

IP地址一般由网络标识(NetID) 主机标识(HostID) 两部分组成,其中网络标识对应着网络地址,表示其局域网属于互联网中的哪一个网络;主机标识对应着一台机器的主机地址,表示机器属于该局域网络中的哪一台主机。

通常情况下,一个IP存在四组数字,每组数字对应着八位二进制数字(一个IP地址共计32Bit),每组之间分别用.隔开,其中不同类型的IP地址,表示网络标识和主机标识的数字段也不同,目前的IP地址主要可分为A、B、C、D、E五大类,如下:

A类IP

A类地址由8位网络标识+24位主机标识组成,也就是之前的四组数字中,第一组表示网络地址,而后三组代表主机地址。网络地址的最高位,即首位必须为0,其中0127都为保留位,因此AIP的网络地址范围为1~126(1.0.0.0~126.0.0.0),也就代表着可用的A类网络有126个,每个网络中最大可容纳一千多万台主机(224-2)。

PS:为什么A类网络的地址范围是1~126呢?

因为AIP中用8bit表示网络标识,首位需要保留为0,因此剩下的7bit能够表示的最大数字为127,末位127也需保留,因此A类网络地址的取值范围为1~126

示意图如下:

例如32.44.128.5这个地址,其中第一段代表网络地址,剩余三段表示网络中的主机地址。

B类IP

B类地址由16位网络标识+16位主机标识组成,因此IP中第一段和第二段都为网络标识,其中前两位为保留位1、0,因此BIP的网络地址取值范围为128~191(128.0.0.0~191.255.0.0),总计可用的B类网络数量为16382个,每个网络中可容纳6万多台主机(216-2)。BIP组成示意图如下:

例如128.123.11.32这个地址,其中前两段为网络地址,后两段表示网络中的主机地址。

C类IP

C类地址由24位网络标识+8位主机标识组成,也就是说,整个IP地址中,前三段都为网络地址,最后一段为主机地址。C类地址中,前三位都为保留位,即C类网络的最高位必须为1、1、0,因此C类网络地址的取值范围为192-223(192.0.0.0~223.255.255.0),粗略计算下来,C类网络的数量可达209万左右,每个网络中允许存在254台主机(28-2),组成示意如下:

192.0.0.121这个IP,前三段为网络地址,最后一段则为网络中的主机地址。

D类IP

D类和后续的E类属于特殊的IP地址,D类地址被称为广播或组播地址,其最高位必须是1、1、1、0,因此取值范围为224~239(224.0.0.0~239.255.255.255),如下:

E类IP

E类地址则属于保留的地址,为以后接入更多的网络预留的IP,其最高位必须为1、1、1、1,即EIP第一段的取值范围为240~255(240.0.0.255~239.255.255.254)

255.255.255.255这个全1IP属于特殊含义的地址,表示当前子网的广播地址,如同全0IP0.0.0.0代表本机地址一样,带有特殊的含义。

IP分类小结

因不同类型的网络IP规模不同,所以它们也分别应用于不同的场景,如:

  • AIP适用于大型网络,由于单个网络中可容纳的主机数非常巨大,因此常被保留给政府机构使用。
  • BIP适用于中型网络,一般会被分配给公益组织、中大型企业等。
  • CIP适用于小型网络,这种IP适用于所有需要网络的个体和小集体,如网吧、家庭、个人电脑等。
  • DIP用于组播。
  • EIP用于保留和实验。
1.1.2、子网掩码

子网掩码又被称为网络掩码、地址掩码、子网络遮罩,它的作用主要有两个:

  • 一、区分IP中网络地址和主机地址。
  • 二、划分子网,扩大网段内的可用IP数目。

但默认的子网掩码值也并非都相同,不同的网络类型存在不同的默认掩码,如:

  • A类网络的默认子网掩码:255.0.0.0
  • B类网络的默认子网掩码:255.255.0.0
  • C类网络的默认子网掩码:255.255.255.0

一个子网掩码决定着一个子网(独立的单个网络)内可容纳的主机数量,计算公式为:可容纳的主机数量=(2n次方)-2。这个n可以理解为二进制掩码中0的数量,例如:

  • A类默认掩码:255.0.0.0转换为二进制为:11111111.00000000.00000000.00000000,后面有240,因此可容纳的主机数量为(224次方)-2,即16777214台主机。
  • C类默认掩码:255.255.255.0转换为二进制为:11111111.11111111.11111111.00000000,后面存在80,因此C类网可容纳主机数量为(28次方)-2,即254台主机。
修改子网掩码为局域网扩容

在中型企业中,经常会碰到一个问题,公司使用C类网,因此子网内可容纳的主机(电脑)数量为254台,但实际公司的电脑可能超出这个数量,如存在440台电脑,那此时如何更改路由器的设置可以让440台电脑同时上网呢?

  • 方案一:增加路由器的数量,更改多个路由器配置。
  • 方案二:通过改变子网掩码的方式为局域网扩容。

,对于第一种方案需要增加经济成本,因此可以暂不考虑。来看看第二种方案,此时将子网掩码修改到多少合适呢?计算过程如下:

  • ①:主机数量/子网可容纳主机的最大数,再向上取整,即:
    • 440/254≈1.73,向上取整结果=2,也就是容纳440台电脑需要2个网段。
  • ②子网掩码决定着子网内可容纳的主机总量,那么设:2N次方≈主机数量,求N
    • 2N次方=440,可算出N>8,即N=9最合适,因此掩码低位应当存在90
    • 即:11111111.11111111.11111110.00000000,转换为十进制:255.255.254.0
    • 因此最终计算出子网掩码为255.255.254.0最合适。

此时假设路由器的LAN口配置是197.118.0.1,那根据第一步计算出的网段数量,分配两个子网段,197.118.0.1~197.118.1.254即可满足需求,采用这种更改子网掩码的方式,就在不增加路由器的情况下,也能达成了为局域网增加可用IP数的需求。

最终可用IP范围为:197.118.0.1/23,可用IP地址共计510个。

嗯?xxx/23是什么东东?其实这个值是子网掩码的简写方式,之前算出来的子网掩码为255.255.254.0,转换为二进制,一共存在231,因此可以简写为xxx/23

如何判断两个IP处于同一个网段

两个IP处于同一网段的前提是:两个IP的网络标识必须一致,那如何计算网络地址呢?

网络地址 = IP地址 "位与" 子网掩码。

如C类网197.118.0.198、197.118.1.114两个IP,子网掩码为255.255.254.0,如何计算网络地址?首先需要将掩码与IP全部都转换为二进制,如下:

  • 197.118.0.19811000101.01110110.00000000.11000110
  • 197.118.1.11411000101.01110110.00000001.01110010
  • 255.255.254.011111111.11111111.11111110.00000000

首先将197.118.0.198网络部分(前三段)的二进制值同掩码进行位与运算,最终可以计算出:

11000101.01110110.00000000,转换为十进制为197.118.0

紧接着再197.118.1.114网络部分的二进制值同子网掩码进行位与运算,计算结果:

11000101.01110110.00000000,转换为十进制为197.118.0

最终可得到结果:197.118.0.198、197.118.1.114的网络地址都为197.118.0,代表着这两个IP处于同一个网段。

子网掩码小结

子网掩码这块的内容,如果你不是专门做网络相关的工程师,哪适当了解即可,如不理解其内容也无关紧要,作为软件开发者并不需要太过深入研究。

1.1.3、IP协议核心流程

经过上述内容学习后,我们已经对IP协议中的IP组成、分类、计算等知识已经建立起了基础,接下来在重点看看IP协议的核心流程。IP协议核心主要包含IP寻址和路由控制。

前面曾提及:网络上任何一台主机都会存在自己的IP地址,那么当应用层数据被封装后,能够精准定位到目标主机的关键原因就在于IP,可以通过IP地址在网络中进行寻址,从而让数据到达目的主机。

但在实际的网络通信过程中,可能有时数据发送的链路非常遥远,如你从中国向日本网友发送一条数据,那么由于一些网络抖动、物理介质损坏都会导致数据丢失。但此时又该如何确保数据"安稳"到达目的地呢?

为了防止数据由于介质损坏或网络抖动等原因丢失,因此会在数据的传输链路中加入一些"中转站",也就是所谓的"路由器",一方面可以备份数据,查看数据是否丢失,如果丢失会重新发送,另一方面也可以控制数据的转发。当然,这个控制数据转发的过程也被称为"路由控制"。

正因为路由控制的存在,所以即使网络复杂多变,也能够通过路由器的控制将数据"安稳"送达至目的主机。

但因数据传输过程中,数据从发送方到接收方之间存在的链路是不可预估的,因此数据传输的链路上可能会分布很多路由器。本质上数据在链路中传输,就是一个个路由器相互之间交换数据报的过程,当然,这个过程也被称为""。

跳:数据包经过一台路由器就是一跳。

好比一个网络中存在四个路由器:A、B、C、D,如果局域网A中的主机要给局域网D中的主机发送数据,从理论上来说就会经过B、C、D三台路由器,也就是会经过三跳。

哪当数据到达某个路由器后,它如何知道"下一跳"该去往何处呢?此时中转的路由器就会解析收到的数据报,然后从中解析出IP数据报,然后查询自身的路由表,从而选择"下一跳"该走的路线,最终不断重复该过程直至数据到达目标主机。这种多次转发数据的过程也被称为"多跳路由"。

1.1.4、IPv4与IPv6

目前的网络几乎大部分还是基于IPv4版本,但同时大部分应用程序也开始支持IPv6IPv6是"Internet Protocol Version 6(互联网协议第6版)"的缩写,是用于替代IPv4的下一代IP协议,也就是下一代互联网的协议。

IPv6相较于IPv4而言,主要不同点在于:

  • ①地址空间不同,IPv4地址采用32位长度,IPv6的地址则采用128位长度。
  • IPv6的路由表会比IPv4更小、更精细。
  • IPv6的组播支持以及对流的支持要强于IPv4
  • IPv6的安全性更高,使用IPv6的用户可对网络层数据进行加密。
  • 协议扩充不同,IPv6允许协议进行扩充,而IPv4不允许。

前述的IP协议分析都是基于IPv4版本而言的,因为目前主流的网络版本还是IPv4,但如今也逐步向IPv6过渡。

1.2、"面向连接"的TCP可靠传输协议

TCP(Transmission Control Protocol)传输控制协议是面向连接的可靠传输协议,是位于传输层的核心协议之一,在不可靠的互联网络上,IP协议只提供了简单不可靠的包交换,但网络中不同主机之间经常需要一种可靠的、类似于管道一样的连接、流机制,去稳定传输一些数据,如视频、音频、图片等大文件数据。

因此TCP应运而生,TCP协议是为了在不可靠的互联网络上提供可靠的端到端之间,字节流传输而专门设计的一个传输协议,TCP中采用字节流传输数据。

1.2.1、TCP协议简介

先来看看TCP的报文头结构:

TCP报文头结构中的各字段释义如下:

  • ①源端口/目的端口:指数据发送方的应用进程端口号及接收方的进程端口号。
  • ②序号:TCP为了保证数据的可靠传输,会对分段数据标注序号,用于组装和确认数据的正确性。
  • ③确认序号:当接收方收到接收到本次数据时,下次需要发送的数据段序号。
  • ④首部:表示TCP报文头的长度,因为TCP头长度可变性,因此需要在头信息中声明每个头的长度。
  • ⑤保留位:预留一些空间给未来拓展时使用。
  • URG:表示本次发送的报文数据中是否紧急数据。
  • ACK:确认信号,当报文中ACK=1的时候表示正确或同意。
  • PSH:表示接收方应该尽快将这个报文交给应用层,为后续数据腾出空间,不要停留在缓冲区。
  • RST:如果收到RST=1的报文,说明与主机的连接出现严重错误(如主机崩溃),必须释放连接,然后重新建立连接。
  • SYN:建立一个新连接,SYN=1表示这是一个请求建立连接的报文段。
  • FIN:断开一个连接,FIN=1表示通知告知对方本段要关闭连接了。
  • ⑫窗口大小:表示现在允许发送的数据量,当到达此值,需要ACK确认后才能继续发送数据。
  • ⑬效验和: 通过CRC算法提供额外的可靠性,用于效验数据正确性。
  • ⑭紧急指针:标记紧急数据在数据字节流中的位置。
  • ⑮选项:这块属于动态的可选择参数。主要选项如下:
    • 最大报文段长度、窗口扩大、时间戳。
  • 数据:报文段传输的数据内容(不属于TCP报文头的范畴内)。

当应用层向传输层传递数据时,TCP会首先对数据流进行分段,将大的数据拆分成一个个的数据报文段,然后会将封装好的数据包传递给网络层的IP层。同时,为了防止数据在网络传输中丢包,TCP也会对每个数据包分配一个序号,当接收方成功收到发送的数据后,会返回一个ACK确认,如果发送方在规定的合理时间(RTT)内未收到接收方的ACK,那么对应的数据包会被认定为已丢失,发送方会将该段数据重新传输。

当数据接收完成后,TCP会用校验和函数来检验数据是否正确,在发送方和接收方都需要计算该值,发送方计算后会将该值放在TCP头中携带发送,接收方接收到数据后,也会再次计算该值,再与报文头中的值进行比对,确认数据的正确性。

1.2.2、连接管理机制 - 三次握手与四次挥手

由于TCP是基于管道连接式通信的协议,因此在数据传递之前,必须要先建立连接,当数据传输完毕后,也必须要关闭连接。因此,这就引出了面试过程中人尽皆知的问题:"为什么TCP是三次握手,四次挥手!"

想要了解清楚这个问题的答案,那么得先了解TCP建立与关闭连接的过程。

TCP的三次握手

所谓的TCP三次握手,其实是指TCP建立连接的过程,因为TCP属于可靠性的传输协议,因此在发送数据前必须要先确保发送/接收数据的双方状态正常,因此需要经过"三次握手"的过程,具体如下:

  • ①客户端向服务端发送建立连接的数据包SYN=1,seq=x,然后进入syn-send等待确认连接状态。
    • SYN=1:代表请求建立连接。
    • seq=x:当前数据包的序号。
  • ②服务端接收到请求建立连接的数据包后,允许建立连接的情况下,会返回响应报文SYN=1,ACK=1,seq=y,ack=x+1给客户端。
    • SYN=1TCP是双全工协议,因此服务端也需向客户端发送SYN=1信号。
    • ACK=1:确认客户端建立连接的请求。
    • seq=y:表示当前服务端返回给客户端的序号。
    • ack=x+1:确认客户端序号x之前的请求都已收到。
  • ③因为是双全工协议,连接是双向的,因此客户端也需确认一下服务端的连接请求,收到服务端的SYN=1后,也需返回ACK=1,seq=x+1,ack=y+1的数据包。
    • ACK=1:表示确认服务端的连接建立请求。
    • seq=x+1:当前数据包的请求序号。
    • ack=y+1:确认服务端序号y之前的数据都已成功接收。

经过如上三个步骤,客户端和服务端双方之间确认请求后,连接会成功建立,紧接着双方都会处于estab-lishen状态,数据可以正常传输。

当然,这个过程略微有些难理解,换个日常生活的例子来快速理解一遍!

  • ①特种兵-竹子:我是竹子,熊猫收到请回答!收到请回答!
  • ②指挥部-熊猫:熊猫收到,我是熊猫,竹子能收到吗?收到请回答!
  • ③特种兵-竹子:竹子收到!竹子收到!
  • 通话开始.........
TCP的四次挥手

当"三次握手"完成后,客户端和服务端之间会成功建立连接,从此开启双方端到端之间的数据传输,当一方数据传输完成后,会尝试中断连接,因此又会经历"四次挥手"的过程,如下:

  • ①客户端完成数据传输后,会发出FIN=1,seq=u关闭连接的报文,然后等待服务端响应。
    • FIN=1:代表请求关闭连接。
    • seq=u:请求序号。
  • ②服务端收到客户端的"关闭"请求后,会给客户端返回确认关闭的报文:ACK=1,seq=v,ack=u+1
    • ACK=1:确认客户端"关闭连接"的请求。
    • seq=v:请求序号。
    • ack=u+1:确认客户端序号u及其以前的数据都已成功接收。
    • 客户端传输完成数据后,会告诉服务端自己要关闭连接了;
    • 但服务端可能数据还未传输完成,因此会继续传输自己的数据,直至自身的数据也传输完成后,也会告诉客户端:自己也要关闭连接了。
  • ③服务端传输完成自己的数据后,向客户端发送关闭连接的报文:FIN=1,ACK=1,seq=w,ack=u+1
    • FIN=1:表示自己也要"关闭连接"了。
    • ACK=1:确认收到了之前的数据。
    • seq=w:请求序号。
    • ack=u+1:确认客户端序号u之前的数据都已成功接收。
  • ④客户端接收到服务端"关闭连接"的请求后,给服务端响应确认报文:ACK=1,seq=u+1,ack=w+1
    • ACK=1:确认服务端"关闭连接"的请求。
    • seq=u+1:请求序号。
    • ack=w+1:确认服务端序号w之前的数据都已成功接收。

前面提及过,因为TCP是双全工的协议,因此双方都可以主动释放连接,在TCP中,当一方数据传输完成后,就会主动关闭连接,也就会经历"挥手"的过程,同样我们也可以举个通俗一些的例子来认识这个过程:

  • ①特种兵-竹子:竹子汇报完毕,请指示!
  • ②指挥部-熊猫:指挥部收到!..&*/?..!^...继续说完自己要交代的任务。
  • ③指挥部-熊猫:这里是熊猫,任务已指示完毕!
  • ④特种兵-竹子:竹子收到!
  • 中断通话.........

三次握手是指TCP建立连接需要发送三个数据包,主要目的是在于:为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。

四次挥手是指TCP关闭连接时需要发送四个数据包,主要目的在于:当客户端发送完数据后,给服务端发送"我要关闭连接了"的请求,然后服务端告知客户端收到了"关闭请求",但此时服务端会继续向客户端传输未发送的数据,客户端也照旧可以接收服务端的数据,直到服务端的数据传输完成后,服务端也会发出"关闭连接"的请求,客户端同意后,最终才会断开连接,从而保证数据正常可靠的交互。

本质上"三次握手与四次挥手"就是在指TCP建立与关闭连接的过程,搞明白建立和关闭连接的过程后再来看看最开始的问题:"为什么TCP是三次握手,四次挥手!"

为什么TCP是三次握手,四次挥手

因为建立连接"握手"时,当服务端接收到"客户端想与服务端建立连接"的请求后,可以立马返回"同意+与客户端建立连接"报文,客户端也确认建立连接后,就可以称为"握手完成"。

但关闭连接时的"挥手",因为一方数据传输完成后就会提出关闭连接,不过另外一方可能还依旧存在数据未发送完成,因此服务端就不能在"确认关闭"连接的时候,也同时发出"关闭连接"的请求,因为自己的数据还没发送完成呢,所以会等到自身的数据全部传输后,再主动向客户端发起一次"关闭连接"的请求,等待客户端"确认关闭"后,从而完成整个"挥手"动作。

1.2.3、TCP中的沾包问题

要理解"TCP沾包"问题之前,首先要理解TCP传输数据的方式。TCP在传输数据时,会给每个分割后的报文段分配一个序号,接收方在收到数据后,会按照序号排好,然后将其放置在TCP缓冲区中。同时TCP为了提升传输速度,若连续几次发送的数据都很少,TCP会根据优化算法把多个数据合并成一个包发出。

沾包问题:多个数据包在一块儿,无法确定每个数据包之间的分割边界,因此从应用层的角度看来,就好像多个数据包"沾"在了一起。

对于TCP传输层而言,发送方和接收方都有可能造成数据沾包问题。

发送发导致的数据沾包问题:TCP为了优化传输速度,往往会等收集到足够多的数据后才发送一包数据,因此发送发传输的数据就出现了沾包问题。

还有一种情况则是:当需要发送的数据大于MSS规定,那么TCP就会对数据包进行拆包,一个数据包会被分开传输,最终导致数据出现沾包问题。

接收方导致的数据沾包问题:TCP中,如果数据被接收后,应用程序没有及时读取缓冲区中的数据报文,就会导致缓冲区中堆积大量的报文数据。这种情况下,站在TCP层的角度而言,看到的是一个个的数据报文依次排列着,但对于应用层的程序来说,看到的就是一串连续的字节流数据,应用程序无法知道每个数据包之间的分割边界,站在应用层的角度来看,所有的数据包就好像都"沾"在一起了一样,应用程序根据预先设定好的大小从缓冲区中接收数据,最终会一次性读取到多包数据。

沾包问题解决方案
  • ①当使用TCP短连接时,不必考虑沾包问题。
  • ②当发送无结构数据,如文件传输时,也不需要考虑沾包问题,因为这类数据只管发送和接收保存即可。
  • ③如果使用长连接,那么则需要考虑沾包问题:
    • 如果发送的报文都是相同的结构,那么可以在首部中添加数据长度,接收方根据首部中记录的数据大小读取数据。
    • 将每个数据包封装成固定长度,不够的用0补齐,接收方每次按照固定大小读取数据即可。
    • 在数据之间设置边界,比如添加特殊符号,这样接收方收到数据时,根据特殊符号分割数据即可。
1.2.4、TCP协议中的其他核心概念

因为TCP既要保证可靠性,同时又要尽可能提高传输性能,所以整个TCP设计的尤为复杂,牵扯出的概念也很多,比如为了保证数据的可靠传输,TCP中提供的机制:

  • 效验和:数据接收完成后进行效验。
  • 序列号:数据按顺序传输和接收。
  • 确认应答:收到数据之后返回ACK应答。
  • 超时重试:超出规定时间后,发送方未收到ACK应答,则会重新再次发送数据。
  • 连接管理:建立和管理连接时,都会经历三次握手、四次挥手确保数据可靠传递。
  • 流量控制:TCP根据接收端的处理能力, 来决定发送端的发送速度,避免丢包。
  • 拥塞机制:TCP采用慢启动机制,由于网络拥塞情况不确定,刚建立连接时会先发送少量数据的包,"摸清楚"网络拥塞程度后,再优化成合适的数据包大小传输。

在确保了数据可靠传输的同时,TCP也提供了一堆机制尽可能提高数据传输性能:

  • 滑动窗口:因为接收一条数据,返回一个ACK这种应答机制大大影响了传输效率,因此TCP中引入了一个新概念:窗口,窗口大小是指无需等待ACK就可继续发送数据的最大值,当收到第一个ACK确认应答后,窗口向后移动,发送后续的数据,因为这个窗口不断向后滑动,所以叫做滑动窗口。
  • 快速重传:结合上述的滑动窗口机制,当某个数据出现丢包时,接收方会持续向发送方传输相同的ACK应答序号,当发送方连续三次接收到相同的应答序号时,就会对该序号的数据报进行重发。
  • 延迟应答:接收方应答速度越快,那么窗口会越小,而延迟应答就是指:接收端稍等一会儿后再发送应答信号,应答速度越慢,窗口越大,网络吞吐量就越大,传输效率就越高(但受到数量和时间的限制)。
  • 捎带应答:在一般数据的传输过程中,大多数情况下都是一发一收的过程,因此ACK应答可以"搭数据的顺风车",和接收方回应的数据报文一起返回,如三次握手中的第二次握手,采用的就是捎带应答机制,ACK应答信号和建立连接的数据报一起发送给了客户端。

同时,TCP协议中,每建立一条连接都会维持九个定时器,可以适当了解:

  • 超时重传定时器:超出规定时间范围后,未收到应答信息,对数据进行重发。
  • 保活定时器:如果已建立的连接超出规定时间后还没有数据交互,则保活定时器超时,向对端发送保活探测包,根据客户端的反馈决定是否继续维持连接,如客户端正常则重置定时器时间,如客户端异常则关闭TCP连接。
  • 持续定时器:也被称为零窗口探测定时器,当接收方缓冲区数据满了之后,会在应答报文中通知发送方将窗口置0,阻止发送方继续发送数据。当缓冲区数据被读取后,会再向发送方发出一个ACK,通知发送方可以继续传输数据,但为了防止该ACK丢失导致死锁现象出现,发送方也会启动零窗口探测定时器,每隔一段时间,发送方会主动发送探测包,迫使接收端响应,从而得知其接收窗口有无打开。
  • ACK延迟定时器:延时应答的定时器,和超市重传定时器功能类似。
  • SYNACK定时器:新建连接时等待ACK应答的定时器,超出时间后会关闭连接。
  • FIN_WAIT2定时器:关闭连接时等待ACK的定时器,超时后会取消"关闭连接"。
  • ER延迟定时器、PTO定时器、TIME_WAIT定时器:这三玩意儿没研究过。

1.3、"面向无连接"的UDP不可靠传输协议

UDP(User Datagram Protocol)协议是传输层的一个不可靠传输协议,它为应用程序提供了一种无需建立连接就可以发送封装的IP数据包的方法。在传输层中,与TCP协议互补,UDP除了给应用层提供了发送数据包的功能外,几乎没有做任何其他事情。而面向连接的TCP恰恰相反,几乎做了所有的事情。

刚刚提到过,UDP仅为应用层提供了发送数据报的功能,主要就是指UDPIP协议的扩充:

  • ①建立在IP协议的基础上,扩展出端口号,可使数据分发到具体的应用程序。
  • ②建立在IP协议的基础上,扩展出数据传输过程中的数据差错效验机制。

接下来先看看UDP的报文头结构。

1.3.1、UDP的报文头

对比TCP复杂的报文头结构,UDP的头部就显得比较简单了,整个头共8字节:

  • ①源端口/目的端口:指数据发送方的应用进程端口号及接收方的进程端口号。
  • ②报文长度:Header+Data的总长度,因为UDP头为8字节,所以该值最小为8
  • 效验和:检测UDP数据报在传输中是否有错,有则丢弃(UDP检验和并非必须的),就算效验时检测出错误,也仅只是丢弃数据包,不会对数据进行纠正,也就是不会重发数据报。
1.3.2、UDP核心流程

UDP是一个无连接的协议,因此采用UDP传输协议的程序,在传递数据时,不会存在建立/释放连接的过程。当数据需要传输时,会对于应用层的数据简单的封装,也就是加上自己的UDP头后,直接会将数据丢给IP层,然后交由链路传输。

正因为如上特性,因此UDP的传输速度仅受到数据生成的速度、计算机算力和传输带宽的限制。

在接收端,UDP会把每个消息段放在队列/缓冲区中,程序每次从队列中读一个消息段。当然,接收端收到数据后,也会对数据做效验,但效验完成后,如若数据存在差错,那UDP只会单纯的丢弃该数据包,不会要求发送端重发数据。

因为由于UDP高效的传输性能,因此常备应用在广播通知、音频通话、视频传输等多媒体数据流业务,而且这类业务中,如果有一个数据包丢失,在很短的时间内就会有另一个新的数据就会替换它,因此就算数据传输不可靠也无关紧要。

1.3.3、UDP中的丢包问题

由于UDP的不可靠传输,因此数据出现丢包是很常见的事情,一般UDP中造成数据丢包的原因主要如下:

  • ①接收端处理数据时间过长,导致不同包之间的数据处理间隔时间过长,造成丢包。
  • UDP单个数据包过大,导致缓冲区快速被填满,接收端程序来不及处理造成丢包。
  • ③发送端数据发送频率过快,接收端处理速度跟不上,从而导致数据丢包。
  • ④发/收双方之间存在网络不稳定,导致数据无法正常分发,从而导致丢包。
  • 一般来说,丢包的原因很简单,要么是网络问题,要么就是接收方处理速度跟不上导致的。
丢包问题解决方案
  • ①如果是数据包过大造成丢包,那么则可以切割数据后分批次发送。
  • ②如果是发送频率过高导致丢包,可以适当控制频率/减小流量,或调大缓冲区。
  • ③如是缓冲区最大了,还是由于处理不过来导致数据丢包,那么可以在程序内再实现一个缓存区,先读取数据到程序中缓存,从而提升接收端的吞吐量。
  • ④如果程序中对于丢包容忍率很低,那么可以自己实现重发机制,或直接切换TCP实现。
1.3.4、TCP与UDP之间的区别
TCP UDP
面向连接 面向无连接
可靠信息传输 不可靠信息传输
字节流传输 报文传输
传输速度慢 传输速度快
仅支持点对点通信 支持一对一、一对多、多对多通信
具备拥塞机制和流量控制 不具备拥塞机制和流量控制
TCP首部至少20个字节 UDP首部仅8个字节
相关推荐
DokiDoki之父2 分钟前
多线程—飞机大战排行榜功能(2.0版本)
android·java·开发语言
想睡hhh6 分钟前
网络基础——Socket编程预备
网络
高山上有一只小老虎7 分钟前
走方格的方案数
java·算法
whatever who cares8 分钟前
Java 中表示数据集的常用集合类
java·开发语言
zzc9219 分钟前
Wireshark获取数据传输的码元速率
网络·测试工具·wifi·wireshark·路由器·802.11n·物理层参数
搬码临时工10 分钟前
端口映射原理操作详解教程:实现外网访问内网服务,本地路由器端口映射公网ip和软件端口映射域名2种方法
网络·tcp/ip·智能路由器
当你需要个夏天21712 分钟前
软考网工选择题-1
网络·智能路由器·选择题·软考网工
极客范儿14 分钟前
新华三H3CNE网络工程师认证—等价路由
网络·智能路由器
Mr_Xuhhh16 分钟前
NAT、代理服务、内网穿透
网络·网络协议·http·https·udp·智能路由器
JavaArchJourney1 小时前
TreeMap 源码分析
java