摘要
帮你速读文章内容
网络通信通过五元组标识,端口号范围0~65535,分为知名和普通端口。UDP无连接不可靠,TCP面向连接可靠。TCP通过确认应答和超时重传实现可靠传输,连接管理通过三次握手和四次挥手。滑动窗口用于控制读写数据量。
摘要由平台通过智能技术生成
有用

一、端口号

在网络通信中,我们以“源IP”,“源端口号”,“目的IP”,“目的端口号”,“协议号”这样的一个五元组来标识一个通信。

端口号的范围划分

端口号的范围是 0~65535,但在这其中还被划分为知名端口号和普通端口号

0~1024: 知名端口号,HTTP,FTP,SSH等一些广为使用的应用层协议,他们的端口号是固定的。

1024 - 65535: 操作系统动态分配的端⼝号. 客⼾端程序的端⼝号, 就是由操作系统从这个范围分配的.

谈到端口号,就要说说与它捆绑使用的进程了。

端口号是有限的,那么是否可以重复利用呢?

一个进程是否能绑定多个端口号呢?

一个端口号是否能被多个进程所绑定呢?

回答一下

一个进程可以绑定多个端口号

一个端口号不能被多个进程所绑定

我们把进程想象成房间,把端口号想象成进入房间的门,是不是就可以具象化的理解了。

到了具体的企业开发中,是这样使用的。

就拿游戏来说

打开游戏,此时游戏就是一个进程,这个进程提供了两个端口号,一个供玩家进入,一个共开发人员进入。

游戏玩家进入游戏,可以享受正常的对局,但是对于游戏内的参数设置以及充值系统不能更改。

而开发人员进入游戏,可以设置对应的游戏参数,调整地图,优化系统,更爱游戏内氪金点数。

二、UDP和TCP

TCP (Transmission Control Protocol) 和 UDP (User Datagram Protocol) 是两种不同的网络传输协议。

2.1 UDP

UDP协议格式

源端口号和目的端口号,标明了这个数据报从哪里来,要到哪里去。

UDP长度: UDP数据报能传输64KB大小的数据

UDP长度在整个UDP数据报中占2个字节,也就是16位,能表示的范围就是0~65535.单位是字节 1024*64=65536。虽然UDP数据报的报头还有8个字节,64KB和64KB-8在实际的开发中,是忽略不计的,只要要传输的数据接近于64KB时,就需要注意了。

UDP校验和: 使用CRC的方式来完成。大致就是通过固定的公式来对要传输数据进行计算得到一个结果,发送方和接收方对两个结果进行比较,如果相等就说明传输的数据没有问题。感兴趣的可以去网上搜一搜相关的介绍,这里不就展开介绍了。

在数字电路中,电平通常用两个状态来表示,分别是高电平和低电平。 高电平表示逻辑1,低电平表示逻辑0。也就是计算机内部的那一串串的二进制数据,当受到电磁波、电信号、光信号的干扰时,可能就会发送比特翻转,造成数据传输的错误。

2.2 UDP的特点

UDP传输的过程类似于寄信.

⽆连接: 知道对端的IP和端⼝号就直接进⾏传输, 不需要建⽴连接;

比特就业课

不可靠: 没有确认机制, 没有重传机制; 如果因为⽹络故障该段⽆法发到对⽅, UDP协议层也不会给应

⽤层返回任何错误信息;

⾯向数据报: 不能够灵活的控制读写数据的次数和数量;

UDP的主要用途

应用于对性能要求高,但是对可靠性要求不高的场景

三、TCP

TCP是一种面向连接的协议,它在传输数据之前会建立一条专用的通信连接。这意味着在数据传输过程中,两台计算机之间会有一条稳定的数据传输通道。因此,TCP可以保证数据传输的可靠性,但会带来一定的延迟

TCP协议格式

16位源端口号和16位目的端口号: 表⽰数据是从哪个进程来, 到哪个进程去;

32位序号: 发送数据每个字节都有一个序号,这个在后续的TCP确认应答机制中会看到实例

32位确认序号: 接收方会给出一个确认序号,这个在后续的TCP确认应答机制中会看到实例

4位首部长度: 这个字段是表示TCP数据报的报头有多大。

4位能表示 0~15,它的单位是‘4个字节’,也就是能表示最大60个字节,也就是表示TCP数据报的报头最大可以是60个字节,在报头部分我们可清楚的看到字段所占据的比特位,只有选项和数据是没有给出大小的。选项包含在报头部分,也就说选项这一部分最多可以表达40个字节大小的数据。

TCP数据报整个报长在协议中没有规定

保留(6位): 这个部分是留白,里面没有任何东西,是设计师预留出的给未来可能出现的功能的位置,

6个标志位:

URG(Urgent): 紧急指针是否有效

ACK(Acknowledgment): 确认号是否有效。*

PSH(Push): 提⽰接收端应⽤程序⽴刻从TCP缓冲区把数据读⾛

RST(Reset): 对⽅要求重新建⽴连接; 我们把携带RST标识的称为复位报⽂段

SYN(Synchronization): 请求建⽴连接; 我们把携带SYN标识的称为同步报⽂段。

FIN(Finish): 通知对⽅, 本端要关闭了, 我们称携带FIN标识的为结束报⽂段

16位检验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含

TCP⾸部, 也包含TCP数据部分.

16位紧急指针: 标识哪部分数据是紧急数据;

选项: Optional(可选项),可以自定义的勾选某些功能

四、TCP的十个核心机制

TCP最核心的机制就是可靠传输

而实现可靠传输就时依靠确认应答机制来实现的,其中超时重传是对确认应答的重要补充。

1.确认应答机制

对于用于应答的数据,称为应答报文

对于序号的解释:

TCP会将每个字节的数据都进行编号,即位序列号

例如:

发送端,发送一个TCP数据报,载荷中的字节TCP会对其进行编号,当接收端接收到数据报后,会获取到数据报中的序号,进行一系列的业务逻辑后,对发送端数据报的序号+1,作为确认序号,并将ACK的值设为1,返回给发送端。

返回的确认序号有两层含义

告诉发送端这个序列号之前的数据我已经全部接收了

请发送端下次发送数据时,从这个序号列开始发送

2.超时重传

在传输过程中出现丢包这种情况,

主机A将数据发送给主机B后,等待主机B的确认应答

当一段时间后还没有收到主机B的确认应答消息,此时主机A就会重新发送。

主机A是如何判断是否收到确认应答的呢?

主机A是通过是否收到了“ACK“来判断是否收到了应答。

如果一段时间内没有收到ACK,那么就认为是发生了丢包,就会重新发送。

那么问题又来了,ACK有没有可能会丢失呢?

答案是 会

如上就发生了丢失ACK的现象。

此时,主机B就收到了两份相同的数据,这样的情况肯定是不能存在的,在你游戏充值界面,你充值了50元,而由于服务器卡顿,给你的账号增加了100快价值的游戏币,肯定游戏厂商不会允许这样的情况发生的。

TCP接收方这边会对接收的数据按照序列号来进行去重。

在TCP重复传输\重复接收是无所谓的,但会保证在应用层不会读取到重复的数据。

那么超时重传的时间间隔是多少呢?

这个时间不是一个固定值,是会随着重传次数的增加而变长,

当时间达到一定阈值,就会重置连接。触发一个”复位报文“来进行尝试重连

但是当网络出现严重的故障时,RST也无法触发重置

只能断开连接(通信双方清除对方的数据 例如端口号 IP地址等)

总结一下

通信是如何实现可靠传输的?

在发送方发送数据时,会对字节进行编号,这个编号连续自增,TCP报头中的序号只存储第一个字节的序号,接收方在接收到全部数据后,会按照接收到的序号+1生成确认序列,这里的确认序号有两个作用,一是说明这个序号之前的数据都已经收到,二是接下来应该发送从确认序号开始的数据,并将报头中的ACK标识符的bit位更改1,生成应答报文返回给发送方。

通信中丢包怎么办?

TCP拥有超时重传这样的机制,当一段时间后,发送方没有接收到来自于接收端的应答报文时,会重新传输数据报。

这里的时间间隔怎么设置?

每次的间隔时间会变长,当到达一定阈值后,就会尝试重置连接

重置连接细节

此时会将报头中的RST标志位的bit位改为1,来进行重置连接。

此时 发送方和接收方就会清除互相的信息(端口号、IP地址等)

通信中出现重复的数据怎么办?

TCP拥有一个接收缓冲区(类似于带有优先级的阻塞队列),当数据到达时,就会进入缓冲区,当应用程序进行read时,就会将数据从缓冲区删除,那么TCP接收会在缓冲区按照序列号来对数据进行去重。

为什么会出现重复的数据?

因为发送方无法分辨是数据丢了,还是ACK丢了,如果是ACK丢了,就会收到重复的数据。

3.连接管理–三次握手 四次挥手

建立连接:三次握手

断开连接:四次挥手

握手:发送一个不含业务数据的数据报,不起到任何业务的作用,只是建立连接。

三次握手

在上述过程中,服务端和客户端各自给对方发送一个SYN,再各自给对方返回一个ACK,实际上是四次交互。

其中,中间的ACK和SYN可以合并成一个数据报(这里是由内核完成的,当收到客户端的ACK同步报文后,立即生成ACK和SYN,这两是同一时刻由内核控制完成的

ACK的bit为1,SYN的bit为1

可以缩减为两次握手吗?

不可以,服务器对于通信双方的接收能力和发送能力的验证没能完成。

那么四次交互不是更直观吗?

这是因为三次的效率比四次要高。

在数据的传输过程中,要经过层层的封装和分用,多一次而带来的消耗就会很大。

三次握手的意义

在数据传输前,先确保通信链路是否通畅

通过三次握手,来确认通信双方的接收和发送功能都是正常的。

还需要协商一些必要的参数。有些参数不是单方面可以确定的,需要双方商量来决定。

三次握手协商

TCP通信时使用的序号,就是通过三次握手协商出来的。

第一次连接和第二次连接,协商出来的起始序号,往往差别很大。

这是为了避免当一个数据报在网络中传输时,可能由于线路规划不明确,导致在网络中一直游转,当通信双方断开连接时生成新的连接时(上一个业务结束,执行下一个业务),此时这个数据报才送到接收端,这时接收端就会根据序号的差异(检查序号时候如果差异过大,就会将这个数据报直接丢弃掉),从而防止上一次业务的逻辑运行到这次的业务中。

四次挥手

客户端和服务端都可以先发起FIN(结束报文)

这里我们假定客户端先发起。

和三次握手是不是有点相似,那为什么三次握手就可以合并两次操作,而四次挥手不可以呢?

四次挥手的FIN和ACK报文可以合并吗?

在特殊情况下是可以的,但一般来说是不可以的。

一般情况

当收到FIN报文时,内核直接就返回ACK报文,而FIN报文是由应用程序来控制的(socket.close),不是同一时刻,所有不能合并。

三次握手是因为SYN和ACK都是由内核控制的,所以可以合并。

特殊情况

TCP有一个延时应答机制,在回复ACK数据报时,不是立即回复,而是等待一段时间,这时ACK和FIN就可以合并成一个报文了。

在服务器看到大量的CLOSE_WAIT,可能是什么原因?

close未调用

close调用不及时

LISTEN - 侦听来自远方TCP端口的连接请求;

SYN-SENT - 在发送连接请求后等待匹配的连接请求;

SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;

ESTABLISHED - 代表一个打开的连接,数据可以传送给用户;

FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;

FIN-WAIT-2 - 从远程TCP等待连接中断请求;

CLOSE-WAIT - 等待从本地用户发来的连接中断请求;

CLOSING - 等待远程TCP对连接中断的确认;

LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;

TIME-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认;

CLOSED - 没有任何连接状态;

为什么会有TIME_WAI?

当服务器给客户端发送FIN后,客户端不能立即释放TCP连接(因为此时客户端还没有发送ACK给服务器,服务器一段时间没收到ACK就会重传FIN,当服务器重传FIN后,客户端还要将ACK返回给服务器,需要服务器的端口号等信息,所以不能立即释放),在一定时间段内,没有收到服务器重传的FIN,就说明ACK已经被服务器所接收。

4.滑动窗口

在日常的业务背景下,有时会处理大量请求,这时,如果再一条一条发送,一条一条接收的话,效率非常低下。此时就引出华东窗口这样的机制了。

没错,就是算法题中的那个滑动窗口。

窗口大小指的是无需得到ACK应答就能发送数据的最大值,图中的窗口大小是2500个字节(五个段)

当一个段接收到ACK后,窗口就会向后移动,然后发送第六个段的数据

操作系统内核开辟了发送缓冲区来记录当前有哪些数据还没有应答,应答了的数据就会从缓冲区中删除。

窗口越大,传输的数据就越多,网络的吞吐率就越高。

如果发现丢包怎么办?

丢的是ACK包: 不影响,因为后续的应答数据报的确认序列会告诉进程,这个序列号之前的数据,都已经接收了。

丢的是TCP数据报: 有影响,

当其中的一个数据报丢失了(例如这个窗口是501~2001,其中501-1000的这个数据报丢失了),那么接收端就会一直向发送端发送同一个应答数据报(要求下一个传输的数据报是从501开始,因为接收端没有接收到501-1000的数据报)

当发送端连续收到这样的同一个应答数据报,就会重新发送501-1000的数据报

当接收端接收到了501-1000的这个数据报,那么就会继续执行,下次执行的就是正在运行的正常的业务的应答数据报。(因为在这个过程中,操作系统内核会有一个接收缓冲区,会将正常的数据报都放在这里面,等处理完异常的情况后,就会根据缓冲区里的数据来继续执行)。

如上这样的处理方式称为快速重传

滑动窗口有什么意义呢?

TCP为了保证可靠性,牺牲了很多的效率,滑动窗口就是为了弥补效率的牺牲,而采取的一种办法。

但是即使采取了措施,效率还是没有UDP快。

5.流量控制

流量控制其实是滑动窗口的一个控制窗口大小的补充。

接收端处理数据的速度是有限的,如果发的太快。接收端还没来得处理,接收端的缓冲区就满了,可能就会发生丢包,引起丢包重传等一系列问题。

因此TCP⽀持根据接收端的处理能⼒, 来决定发送端的发送速度. 这个机制就叫做流量控制(FlowControl);

6.阻塞控制

和流量控制一样,是为了辅助滑动窗口使用的。

数据在网络的传输中,会经过很多网络结点。传输的速度就会受到这些结点的限制。

为了探寻传输数据的的最高效率,引入了阻塞控制

工作流程如下

最开始按照小的速度,小的窗口来发送数据

如果没有丢包,就加大速度,增大窗口,继续发送

增加到一定程度,出现了丢包现象,就立即减小速度,缩小窗口

当没有丢包情况出现后,就继续加大速度,增大窗口

上述操作持续进行,直到找到一个阈值。

流量控制的窗口和阻塞控制的窗口选择哪个呢?

谁小听谁的

注意

阻塞控制的窗口变化也是有相应的规律的。

慢开始: 先以小的窗口传输数据,主要是检测通信路径是否通畅。

**扩大窗口①:**以指数的形式来扩大窗口。

**扩大窗口②:**到达某个阈值,就开始线性扩大窗口

缩小窗口:

①:窗口直接缩小到0,再重复上述流程,

②:窗口缩小一半,然后线性的增长窗口。

7.延迟应答

在接收方接收到数据后,并不立即返回ACK,而是隔一段时间再返回ACK,这样可以提高传输速率

窗口越大,网络的吞吐量就越大,也就是说网络传输的速度也就越快

当接收方接收到数据后,处理数据需要时间,而延迟应答的这一段时间正好就可以处理数据,处理完数据后,缓冲区的空闲窗口就会变大,从而由流量控制来进行响应给出反馈,从而使得传输速度变快。

说到延迟应答,就又跟四次挥手联系在一起了,延迟应答这种机制就可以将四次挥手给合并成三次挥手哦,不过这只是特殊情况。一般的情况就还是四次挥手。

** 延迟应答的时间的规划**

按照一定的时间来应答,一般是200ms

按照收到的数据报个数来应答,一般是两个包

8.捎带应答

捎带应答 就是将两个数据报的内容在满足业务逻辑的情况下,将几个数据报合并在一起。

例如在三次挥手中,就将ACK报文和SYN报文合并在一起了。

这样做的意义:

可以调高效率,减轻服务器的压力,因为一次数据的传输,需要经过层层的封装和分用,,将两次操作合并成一次,减少了很多工作量。

9.粘包问题

首先我们要明确,粘包问题粘的是应用层的数据报

为什么会出现这样的情况?

因为TCP协议报头并没有像UDP协议一样报头中有着报文长度这样的属性字段,所以不能确定一个数据报是多长而进行分割

站在传输层的角度来说,TCP是一个一个报文来的,按照序号排放在缓冲区中.

站在应用层的角度来说,看到的只是一串连续的字节数据,

应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分结束是一个完整的数据包。

说了这么多,那么该如何让避免呢?

使用分割符: 定义任意字符,来作为分隔符。例如用空格作为分割符来将包与直接分割开。

约定包的长度: 在发送数据包之前,也将这个数据包的长度一同发送过去,从而就知道了包的结束位置

10.异常情况

一个进程崩溃

进程终⽌会释放⽂件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.

操作系统内核都会回收释放对应PCB,可以释放文件描述符表,相当于close。也会正常的进行四次挥手,一定会完成四次挥手。

主机正常关机

这时,操作系统先会强制结束所有的进程,正常的进行四次挥手,但不一定会完成四次挥手,但是不影响。因为当发送了FIN后没有接收到ACK或者接收到ACK后,A进程结束,此时B的FIN会重复传送几次,如果重传了几次还是没有收到A的ACK,那么B还是会把A的信息(IP地址,端口号等)删除,此时A已经关机了所以A中B的信息也删除了。

主机电源断开

分两种情况来分析:

当接收端的电源断开时

发送端接下来发送的数据,都不会有ACK了

那么就会触发超时重传,重传几次之后,就会发送复位报文RST,当复位报文也没有响应时,发送端就会删除接收端的信息。

当发送端的电源断开时

接收方会在一段时间没有收到来自发送方的数据时,会触发一个心跳包,

心跳包的特点:有周期,有心跳就说明进程没有关闭

在接收方发送了几次心跳包后,没有收到回复,那么就会认为发送方进程已经结束,就会删除发送端的信息。

网络断开

本质也就是第三种。

举报/反馈

外太空的金山

1.6万获赞 4017粉丝
通信工程小白,学习中分享知识
关注
0
0
收藏
分享