网络原理(三)—— 传输层 之 UDP 和 TCP协议

鼠扑  论坛元老 | 2025-1-14 17:43:48 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 2017|帖子 2017|积分 6051

传输层

在传输层两大关键的协议就是UDP和TCP协议了,除此之外,另有别的传输层协议,本文章将先容UDP和TCP协议,重点先容TCP协议。
首先回首TCP和UDP 的特点:
UDP:不可靠传输,面向数据包,全双工
TCP:可靠传输,面向字节流,全双工
UDP 协议

UDP报文格式:

源端口号和目的端口号耳熟能详了。
UDP长度是指整个UDP数据包的长度(报头 + 载荷),由于是16位的长度,所以整个UDP数据包最大的长度就是 2^16-1 个字节(单位是字节)即 64KB
16位UDP校验和是校验UDP数据包有没有堕落,这和 https 的校验和不一样,https 是为了防止有人窜改数据,这里的UDP校验和是为了防止出现比特翻转(0->1,1->0),也就是防止原始数据发生比特翻转导致数据错误。
末了就是载荷内容
UDP 数据包的报头固定是64个比特位也就是8个字节。
由于UDP最大长度是68KB,在如今的互联网期间,远远不敷用,所以引入了下面的 TCP 协议。
TCP 协议

TCP报文的格式:

32位序号:该报文的载荷数据的第一个字节的起始编号
32位确认序号:说明该报文的确认报文,确认序号说明自己已经接收到的末了一个数据包的末了一个字节的编号+1,也就是你下一个数据包发送的序号应该凑够这里开始。举个例子:假设一个数据包序号为1000,载荷数据占1000字节,对方正常接收,之后需要返回一个确认报文,该报文的确认序号应该是2001。说明2001前面的全部的数据包已经被接收了。
4位首部长度是指首部最大的长度是多少,单位是(4字节)。说明TCP报头的最大长度就是 (2^4 -1)* 4 = 60 字节
确认应答

确认应答是指当一方发送数据到达另一方之后,另一方需要返回一个确认数据包,这就是包管可靠传输的此中一种包管。
在TCP报头中我们发现一个有六个标志位的部分:

当 ack 为 1 的时间,说明这是一个确认应答的数据包。
超时重传

当一方发送完数据包之后,如果迟迟未等到确认应答的话,就会以为改数据包发生了丢包了,因此为了包管可靠传输,我们需要举行重新传输改数据包,这就是超时重传。
   包管可靠传输的关键就在于确认应答和超时重传。
  连接管理

三次握手

在客户端和服务器建立连接的时间,TCP使用的是三次握手的流程。
首先服务器是被动接收客户端的请求,因此建立连接的发起者肯定是客户端,客户端首先发送一个同步报文,然后服务器接收到同步报文之后,就会返回一个确认应答和同步报文,末了客户端返回确认应答数据包。

同步报文的特点是 六个标志位里的 syn 是 1.
   为什么是三次握手???
首先TCP是有连接的,详细体如今客户端和服务器分别保存了对端的信息。
连接的建立还需要确保双方的发送能力和接收能力都没问题,能正常举行数据通信。
因此客户端发送syn,如果服务器正常接收,说明客户端的发送能力没有问题,这时间服务器发送syn+ack,此时客户端如果额能正常接收的话,说明客户端知道服务器可以正常接收和发送数据,但是服务器这边不知道客户端是否能正常接收数据,因此客户端需要再次发送一个数据包也就是确认应答数据包ack,服务器接收完毕之后,双方就都确定了对方的接收和发送能力正常,也保存了对端的信息,可以开启会话。
    由于我们把 syn 和 ack 归并在一起发送给客户端,所以只需要一次,而不是两次,因此四次握手就没有很大的必要了。两次握手又不足以验证双方各自的发送和接收能力正常
    三次握手的作用:
首先开端验证通信链路是否是通畅的
验证双方各自的发送能力和接收能力是否正常(这就是为什么两次握手不可)
协商关键信息(序号是从哪里开始的)
  三次握手的状态:

当服务器步伐一启动,就会由 CLOSED 状态 切换为 LISTEN 状态。
LISTENED 状态:服务器已经启动,可以随时连接客户端
SYN_SEND 和 SYN_RCVD,分别是 syn 发送和接收状态,一般很难看到,由于TCP连接的建立很快就能发生。
ESTABLISHED:是连接建立完毕的状态,随时可以举行数据通信
四次挥手

首先明确一点就是客户端和服务器都可以自动断开连接。
断开连接一般是四次挥手:

自动申请断开连接的需要先发送一个 FIN 数据包(标识位FIN 为1)
然后接收到 FIN 数据包之后需要返回 ACK
接着发送 FIN
末了 返回ACK
TCP连接就会释放
   为什么三次握手第二次的数据包SYN可以和ACK 一起,而四次挥手的中心的 FIN 和 ACK 不能归并呢?
由于三次握手的第二份数据包中SYN和ACK 是由内核决定的,当接收到客户端的SYN 之后,会立即返回syn+ack
然而四次挥手的ack 是由内核决定的,但是 FIN 是由应用步伐的代码决定的,当步伐执行到 socket.close 之后,才会发送 FIN 数据包

  四次挥手的状态:

这里要注意的是:谁先发送 FIN,谁就会进入到 TIME_WAIT 状态
谁后发送FIN ,谁就会进入到 CLOSE_WAIT 状态
异常情况的处理

这里列出四种异常情况。
一、进程崩溃了
进程崩溃和自动退出没有本质区别,虽然进程崩溃了,但是只是应用层不可了,传输层的TCP连接还是存在的,因此这里会发生四次挥手来释放连接
二、主机正常关机了
正常的主机关机流程,关机需要肯定的时间,在这段时间中可以举行四次挥手
三、不正常关机
如果是不正常关机,例如台式机断电,那么四次挥手可能就没有挥完。举个例子,如果A关机之前发送了一个FIN,在收到 B 的 FIN 之后,A已经关机了,这就意味着B是永远都收不到 ACK的了,那么由于 B 迟迟没有收到 ACK,那么首先会以为发生了丢包,举行超时重传,当超时重传几次之后还是没有收到ACK,就会以为对端发生了严峻的错误,B就会自动放连接。

上面的情况是A发出去 FIN 之后,如果A突然断电,没有发送FIN:
1)接收方突然断电
那么这时间 发送方 发送的业务数据迟迟没有得到确认报文,那么 发送 首先会以为发生丢包开始举行超时重传,等到多次迟迟没有得到回应,这时间就会发触发 “重置TCP连接”,发送复位报文(标识位RST为1),【复位报文是指重新建立连接,重新来过发送数据】如果没有得到ACK,那么服务器会片面断开连接。
2)发送方突然断电
这时间客户端不知道是服务器挂了还是服务器只是没有继续发送数据了,那么客户端就会先等着,等候到肯定时间之后就会发送一个 “心跳包”,(心跳包只是为了触发ack,确认一下服务器是否存活,不携带任何业务数据)【这个也叫做保活机制,但是由于TCP发送心跳包的时间过长,一般我们会在应用层重新实现心跳包的逻辑代码】
四、网线断开了
这种情况,站在 A 的视角会以为是第三种情况,A末了会放弃连接
站在B 的视角会以为是第三种情况,B会自动放弃连接。
滑动窗口

由于TCP是可靠传输,那么必定会影响到传输的效率,相比于UDP来说,TCP的传输效率是远远小于UDP的。为了在可靠传输的基础上尽可能进步传输效率,我们使用滑动窗口的概念。
这里的窗口是指接收方的缓冲区的大小,最多可以容纳多少个TCP数据包,当接收方接收完数据后一般会返回ack,此中 ack 里面就会包含接收方剩余窗口容量(对应的就是16位窗口大小),这样发送方就可以根据窗口
大小来举行批量传输数据,就不用一个一个地逐步传输了。
   16 位窗口大小并不是窗口大小的极限值,在TCP报头里另有一个叫做选项的数值,里面有一个数值是窗口扩展因子,假设窗口扩展因子为2,那么窗口大小要左移( << )两位
    滑动窗口不能无穷大,大了会影响传输效率。
  快速重传

由于接收方有窗口(缓冲区),所以如果此中有一个数据包发生了丢包就会触发快速重传谁人丢失的数据包,然后继续之前的传输。由于数据包已经在缓冲区分列好了,不需要重新重传已经发送过的数据包

流量控制

流量控制是调整发送方的传输速率,避免接收方不能及时处理数据就导致丢包,那么我们就会引入流量控制。
当接收方处理不过来的时间,发送方会低沉发送的速率;当接收方还可以继续处理更多的数据的时间,发送方会进步传输的速率,这就是流量控制。
拥塞控制

由于传输效率还与当前网络的链路有关,如果当前网络占用率高,那么发送方就要低沉发送速率,如果当前网络链路占用率低,可以进步发送速率。

慢启动现在已经被弃用,如今使用的是快启动。
首先有一个窗口的阀门值,先发送一个数据包,每轮传输的数据包数量即是前一轮传输的数据包数量 * 2,直到达到窗口的阀门值,之后每轮传输的数据包会 + 1,也就是开始是指数增长的,达到阀门值之后就变成线性增长了。
假设当前窗口大小调整到了24,如上图所示,这时间已经到了网络链路的极限的时间,也就是发生了丢包,发送方收到了连续的 3 个 ack 之后,就会举行快启动,如今窗口阀门值会变成当前窗口的 1/2 也就是 24 / 2 = 12,发送数据量会降到新的阀门值,之后继续举行 + 1 的线性增长
如果是慢启动,新的窗口阀门值还是当前极限窗口的 1/2 也就是12 ,这时间传输的数据包的数量降为1,重新开始 * 2 的指数增长到达阀门值然后举行 + 1 的线性增长
从快启动和慢启动的区别来看,快启动会效率高一些,所以如今我们使用的是快启动。
   窗口的实际大小即是 MIN(流量控制的窗口值,拥塞控制的窗口值)
  延迟应答

当接收到数据的时间不立即返回 ack,而是等一会再返回 ack,这就是延迟应答
延迟应答可以让接收方有一些时间先处理一下缓冲区(窗口)的数据,这样等一会,窗口就会变得大一些,那么 ack 返回的窗口的大小就可以大一些,那么发送方就可以批量传输更多的数据了,再肯定程度上进步了传输效率。
捎带应答

就是在返回 ack 的时间顺便把业务数据也一起带上,捎带应答是配合延迟应答使用的,延迟应答一般是等到接收方需要发送业务数据的时间把 ack 一起带上,这样可以减少网络开销,在肯定程度上进步了传输效率。
面向字节流 —— 粘包问题

由于TCP是面向字节流的,所以在拆包之后,数据可能发生粘包问题,就是拆完包之后分不出哪些数据是一组,哪些数据是另一组。
举个例子,发送方发送 aaa, bbb, ccc 这三个数据包,在接收方的传输层里举行拆包然后数据就可能变成这样 aaabbbccc,交给应用层的时间就无法区分了,这就是粘包问题。
要解决粘包问题需要在应用层处理,在传输层是无解的,在计划应用层协议的时间,我们需要界说好如何区分这些数据,可以像之前我们写TCP回显服务器和客户端一样,使用 \n 这个换行符来举行数据的分割,或者其他的分割方法。
   口试题:如何让UDP 实现可靠传输??
参考 TCP ,例如:添加序号,确认序号,引入确认应答,超时重传…

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

鼠扑

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表