【传输层协议】UDP和TCP协议

news2024/11/25 4:46:51

UDP协议

UDP协议全称为User Datagram Protocol,用户数据报协议。UDP协议报文格式如下:
在这里插入图片描述

  • 16UDP长度。表示整个数据报的最大长度,即UDP首部+UDP数据。这个字段帮助我们确保在网络字节流中获取完整的UDP报文信息
  • 校验和:用于检测数据报在传输过程中是否发生错误。

UDP特点

  • 无连接:UDP不需要建立连接就可以发送数据,这意味着在发送数据之前,发送方和接收方并没握手过程
  • 不可靠传输:UDP不保证数据包的到达顺序,也不保证数据包一定到达(没有应答)。这意味着数据包可能丢失了都不知道或者乱序达到。
  • 低开销:因为不用维护连接,也不用保证传输的可靠性,UDP的报头只有8字节,开销比较小。
  • 面向数据报:面向数据报又叫面向消息。面向数据报的意思就是应用层给UDP多少数据,UDP的数据部分就有多少,既不会拆分也不会合并(不灵活)
  • 传输的数据量少:16位长度包括首部也就64k,相当有限。如超过这个范围就需要在应用层手动分包,多次发送,接收后也要采取手段拼装。

UDP的缓冲区

  • UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
  • UDP具有接收缓冲区。但是这个接收缓冲区不能保证收到的UDP报文和发送报文的顺序。如果缓冲区满了,再到达的UDP报文就会直接被丢弃。
  • UDP 的 socket 既能读, 也能写, 所以是 全双工

基于UDP的应用层协议

  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

TCP协议

TCP协议的全称为传输控制层协议(Transmission Control Protocol)。下面是TCP报文的结构:
在这里插入图片描述
显然,TCP报文首部要包含的信息比UDP多很多,下面来分析各个字段的作用。

  • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去

  • 32位序号:表示发送数据的字节序号,用于数据重组,该字节序号与发送缓冲区的字节序相关联

  • 32位确认序号仅在ACK标志置位时有效,表示期望接收的下一个字节序号。

  • 4 位 TCP 报头长度:表示TCP头部的长度(以4字节为单位),最小值为5。也就是说如果这4位报头长度的为5,那么实际表示报头的长度就是5*4=20字节。

  • 6位标志位:

    • URG:紧急指针有效。
    • ACK:确认号有效。
    • PSH:提醒接收方尽快读取接收缓冲区的数据
    • RST:重置连接,携带该标志的报文也称为复位报文段
    • SYN:同步序号,用户建立连接,携带该标志位的报文也称为同步报文段
    • FIN:表示发送方已经发送完毕,需要关闭连接,携带该标志位的报文也称为结束报文段
  • 16位窗口大小:表示接收方的窗口大小,用于流量控制。如果该值比较大,那就可以一次多发点报文,否则就一次少发一下。

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

  • 16 位紧急指针: 一个偏移量,标识哪部分数据是紧急数据。这个指针只在URG标记位为1时生效。

  • 40 字节头部选项: 可变长度,用于定义附加选项,比如最大报文段长度(MSS)、时间戳等。假如窗口大小大于16位,就可以附加增大窗口大小的选项。

确认应答机制

TCP为了保证数据传输的可靠性,在每次发送端发送数据之后**,接收端要发送一个携带ACK标记位的报文(后面简称为ACK),来告诉发送端消息已经收到**。这也就意味着,只要发送端收到了ACK,就可以继续发后面的数据了。
在这里插入图片描述
TCP 将每个字节的数据都进行了编号. 即为序列号,如下图:
在这里插入图片描述
每一个 ACK 都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.假如发送方发送了字节序号为1-1000的数据,也就是说16位发送序号为1000。当接收方收到数据后,根据发送序号,再发送一个确认序号为1001的ACK报文,提醒发送方1001之前的字节数据已经收到,下次应该发送1001号字节开始往后的数据。

超时重传机制

在这里插入图片描述

如果发送端发送报文之后长时间没有收到接收端发过来的ACK,那么说明可能是由于网络拥堵丢包了根本没到达接收端,也有可能接收端已经收到且发送了ACK,只不过ACK由于某种原因丢失了。这个时候发送端就会重新发送一个一模一样的报文。这种机制就称为超时重传机制
关于超时重传,解释以下几点:

  • 如果接收端收到了重复的数据该怎么处理呢?
    根据报文中的序列号排序,如果该序列号的数据已经有了,那接收方就直接丢弃这个多余的报文。

  • 超时的时间该如何确定?

最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”.但是这个时间的长短, 随着网络环境的不同, 是有差异的。
为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间: Linux中,超时以 500ms 为一个单位进行控制, 每次判定超时重发的超时时间都是 500ms 的整数倍. 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.
累计到一定的重传次数, TCP 认为网络或者对端主机出现异常, 强制关闭连接.

连接管理机制(握手和挥手)

在正常情况下, TCP 要经过三次握手建立连接, 四次挥手断开连接。具体过程如下图:
在这里插入图片描述

服务端状态转换过程

  • [CLOSED -> LISTEN] 服务器端调用 listen 后进入 LISTEN 状态, 等待客户端连接;
  • [LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段),收到第一次握手, 就将该连接放入内核等待队列中, 并向客户端发送 SYN 确认报文,这是发起第二次握手
  • [SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文, 就进入ESTABLISHED 状态, 可以进行读写数据了.(收到第三次握手
  • [ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用 close),即收到第一次挥手 , 服务器会收到结束报文段, 服务器返回确认报文段(发起第二次挥手)并进入 CLOSE_WAIT;
  • [CLOSE_WAIT -> LAST_ACK] 进入 CLOSE_WAIT 后说明服务器准备关闭连接(需要处理完之前的数据); 当服务器真正调用 close 关闭连接时(发起第三次挥手), 会向客户端发送FIN, 此时服务器进入 LAST_ACK 状态, 等待最后一个 ACK 到来(这个 ACK 是客户端确认收到了 FIN)
  • [LAST_ACK -> CLOSED] 服务器收到了对 FIN 的 ACK, 彻底关闭连接.(收到第四次挥手)

客户端状态转换过程

  • [CLOSED -> SYN_SENT] 客户端调用 connect, 发送同步报文段(发起第一次握手
  • [SYN_SENT -> ESTABLISHED] connect 调用成功(收到第二次握手), 则进入 ESTABLISHED 状态。发送ACK给服务端(发起第三次握手),开始读写数据
  • [ESTABLISHED -> FIN_WAIT_1] 客户端主动调用 close 时, 向服务器发送结束报文段, 同时进入 FIN_WAIT_1(发起第一次挥手
  • [FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认(收到第二次挥手), 则进入 FIN_WAIT_2, 开始等待服务器的结束报文段
  • [FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段(收到第三次挥手), 进入TIME_WAIT, 并发出 LAST_ACK(发送第四次挥手

TIME_WAIT状态

TCP 协议规定,主动关闭连接的一方要处于 TIME_ WAIT 状态,等待两个MSL(maximum segment lifetime)的时间后才能回到 CLOSED 状态.此时已经发起了第四次挥手,为了保证这个第四次挥手能被接收方接收到,所以需要等待一段时间。当然,这个ACK也有可能丢失,那么服务器会再重发一个 FIN
MSL 在 RFC1122 中规定为两分钟,但是各操作系统的实现不同, 在 Centos7 上默认配置的值是 60s;
这也是为什么有时候主动关闭服务端,马上重启不能绑定同样的端口。这是因为上一个关闭的服务端可能还处于TIME_WAIT状态,还没有彻底的断开连接释放套接字。

同时,等待一定的时间再关闭套接字,也是为了两个传输方向上还没有被接收的数据的报文段都已经消失,保证下次重启同一个端口的服务器不会收到旧数据

CLOSE_WAIT状态

如果服务端第一次收到客户端发来的FIN报文,发送ACK报确认后服务端就会进入CLOSE_WAIT状态。此时服务端已经知道对方要关闭连接了,自己也要准备关闭了。

在这个状态下的服务端依旧可以向客户端发送数据报,虽然客户端关闭了连接,但依旧可以收报文(接收缓冲区没有关闭)。直到服务端调用close函数,才会结束这个状态。如果应用程序没有及时调用close函数,连接会长时间停留在CLOSE_WAIT状态。这样就会导致资源泄露(如文件描述符耗尽),影响服务器性能

为什么是三次握手和四次挥手

换个问题,为什么三次握手就能保证建立可靠的连接呢?

  • 确认对方主机状态及收发能力的最小次数。三次握手保证了双方网络的连通性,也保证了双方连接的意愿,还保证了双方拥有接收和发送数据的能力。
  • 如果只有一次握手,意味着只要发送方发送连接请求,连接就会被建立。那这样服务端容易收到SYN洪流攻击,即服务端建立大量的连接对象消耗太多资源从而导致奔溃。两次握手也是类似,服务端收到一次连接,只要服务端发出一次ACK,就说明连接就建立起来了(发送方可以不要这个ACK,而是只发SYN)。如果有不法分子恶意发送大量的SYN,服务器依旧会创建对应的连接对象,依旧非常消耗资源。
  • 如果是三次握手,客户端建立连接和服务端建立连接的代价是一样的,同样需要发送ACK,否则连接就会失败。也就是说,双方是对等的,变相的客户端连接的成本提高了,也就不容易搞垮服务器
  • 四次握手也可以,只不过再多的握手达到的效果和三次是一样的,那为什么还要浪费时间去多握手呢?

为什么是四次挥手而不是像握手一样进行三次挥手?
因为当客户端发起第一次挥手之后,只是意味着不再向服务端端发送数据包,不代表不能接收数据包。有可能服务端处理的数据包还没被客户端接收,此时彻底关闭连接就丢失数据了。所以客户端需要有一个时间间隔来读取服务端发送的数据包,什么时候接收方发送完了呢?就是等服务端也发起挥手的时候,此时就代表服务端发送完了,客户端也不需要再收取数据了。

同样的,四次挥手保证了通信双方都有关闭连接的行为,且都能得到应答,也就是说对方都能知道你要退出。这样就保证了数据传输的完整性。

五次挥手?和不需要四次握手是一样的道理。

滑动窗口

滑动窗口是TCP保证传输效率的一个重要手段。具体来说,滑动窗口维护了一个报文区间,处于这个区间的报文都可以暂时不考虑应答直接全部发送。如下图。在这里插入图片描述
更详细的:

  • 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值. 上图的窗口大小就是 4000 个字节(四个段).
  • 收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据;窗口向右移动。
  • 窗口越大, 则网络的吞吐率就越高

在这里插入图片描述
对于滑动窗口,解释以下几点:

如果发生丢包如何进行重传?

由于一次发送多个报文,丢包的概率就会上升。那么发生丢包之后如何进行重传呢?下面分情况讨论。

  • 情况一:数据包到达,但是ACK确认 丢了
    在这里插入图片描述

回顾之前TCP报文中的确认序号的作用,即告诉发送端下一次发送数据应该从哪个字节序开始,换句话来说,假设ACK的确认序号为2001,则表示1-2000的数据全部都收到了。这样一来,即使中间有ACK丢失,只要后面有ACK没有丢那就不影响。比如确认序号为2001、3001的ACK都丢失了,但是4001没有丢失,那么接收端就会认为4000以前的数据都被收到了,即使没有收到2001和3001的ACK

  • 情况二:数据包丢失
    这种情况接收方并没有收到部分数据包,也就不会发送ACK应答。假设前面字节序的数据包丢失,接收端在收到靠后的数据包后,通过对数据包排序会检测最前面还没有收到的字节序,并以此发送ACK。例如:
    在这里插入图片描述
    上图中一次发送了7个数据包,发送序号依次为1000、2000到7000。现在第2个数据包丢失,即发送序号为2000,接收方只收到了字节序1000和3000-7000的数据,这个时候,接收方发现最前面的2000个字节的数据还没有收到,发送的ACK的确认序号就是1001,表示1001以前的数据全部收到。为什么不发送3001或者7001呢?这是因为如果发送ACK的确认序号为3001的话,发送方就会认为1-3000的数据都被成功接收了,可实际上不是。也就是说,7个报文中,最后接收方成功收到了6个报文,且这6个报文的ACK全部都是1001
    当发送方连续收到的3个相同的1001ACK时,就会重新发送1001-2000的数据包。这种机制就称为高速重发控制,也称为快重传。为什么说是高速呢?因为这种机制减少了发送端的等待重传的时间。当然,如果没有收到3个,即最后只有两个报文丢失了前面的一个,这个时候发送方就会超时重传利用快重传和超时重传,即保证了数据传输的可靠性,也一定保证了传输的速度

流量控制

接收端处理数据的速度是有限的,如果发送端发送的太快就会导致接收端的接收缓冲区打满。这个时候如果发送方继续发送数据包就会造成丢包。
TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制
具体是怎么做到的呢?
上面我们已经说过,TCP报文中用16位比特位表示窗口大小,由于窗口是根据接收方的实际接收缓冲区变化而变化的。所以,如果收到的报文中窗口大小字段比较大,那么说明接收方的接收缓冲区还有很多剩余空间,这个时候就可以一次多发一点数据包,否则就可以少发一点。这样就达到了控制流量的效果。

此外,如果接收端的缓冲区满了,就会把窗口值设为0。这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.也可以设置PSH标记位来提醒接收端快点从缓冲区里读数据
在这里插入图片描述
本质上,所谓的窗口探测报文就是一个极少数据量的TCP数据包,和普通报文没区别,只是为了获得ACK的窗口大小

拥塞控制

虽然 TCP 有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是还可能会受到网络情况的影响。比如网络现在比较拥堵即使接收方的窗口大小还很大,发送方发来的数据被堵在网络中,依旧达不到高效传输的目的,而且还很有可能加重拥堵。为了解决这个问题,或者说避免加重有拥堵,引入拥塞窗口的概念。

既然接收缓冲区的窗口大小直接表示了缓冲区接受数据的能力,那么拥塞窗口的大小也能直接表示当前网络的拥塞情况,拥塞窗口越大表示网络越不拥堵,相反则越拥堵

那发送方如何根据拥塞窗口来调整自己的发送数据包的量呢?

  • 如果发送方总是收不到ACK,那么说明丢包率比较高,此时就可以判断网络已经阻塞了。
  • 此时就不能发送太多的数据包,否则就会加重阻塞。开始发送一个数据包,并定义拥塞窗口的大小为1,每次收到一个 ACK 应答, 拥塞窗口加 1;
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取 较小的值 作为实际发送的窗口;

慢启动

慢启动是TCP拥塞控制的一部分,用于在连接建立或重传超时后逐步增加拥塞窗口的大小,以避免网络拥塞。与其名称相反,慢启动的实际增长速度非常快。(只是指开始启动慢)

发送方每次发送的报文数量是上一次的的两倍,即2的n次方的速度增长。具体过程如下图:
在这里插入图片描述

  • 但是指数增长的太快了,为了限制增长速度,需要设置一个慢启动阈值。慢启动阈值是一个预设值,用于限制慢启动阶段的指数增长,当拥塞窗口的大小达到了阈值,就不再按照指数方式增长, 而是按照线性方式增长
  • 当 TCP 开始启动的时候, 慢启动阈值等于窗口最大值;
  • 如果又遇到了网络阻塞,就会重新慢启动,且本次慢启动的阈值是上一次最大拥塞窗口的一半。

延迟应答

如果接收数据的主机立刻返回 ACK 应答, 这时候返回的窗口可能比较小.此时可以采用延迟应答,即不立刻返回ACK,而是等一下,等待的时间里可能接收端会从从缓冲区中处理一些数据,到时候发送的ACK的窗口大小就会大一点,发送方收到后也就可以多发一点数据包。

当然,延迟的时间肯定不能太长(有最大延迟时间),不然发送端就超时重发了。
在这里插入图片描述

捎带应答

如果接收方收到了发送方的数据包,发送的ACK报文可以携带其它的数据,从而减少单独发送确认报文的次数。这就叫做捎带应答。比如第二次握手的过程,就是ACK标记位和SYN标记位一起生效发给接收方
在这里插入图片描述
为什么第二次挥手的时候不能使用捎带应答的方式来减少挥手次数呢?
这是因为,服务器收到FIN报文后,发送一个ACK报文确认接收到了客户端的FIN报文,同时服务器可能还在发送一些未完成的数据。也就是说,即使收到发送方的关闭请求,服务器还是需要向接收方发送消息,中间需要时间

粘包问题

粘包是指在接收端读取数据时,可能会将多个发送端的数据包拼接在一起(粘在一起),或将一个数据包拆成多次读取。这通常发生在基于流的传输协议(如TCP)中。

每个UDP数据包都是一个独立的报文,具有明确的边界。因此,UDP协议本身不会出现粘包问题。每次调用recvfrom或recv函数时,都会接收到一个完整的UDP数据包。
但是TCP接收方按照固定长度读取数据,就可能读取不完整或者是一次读取多个数据包。因此需要使用特殊字符(如换行符、空格等)作为数据包之间的分隔符。接收方根据特殊字符来拆分数据包

总结TCP

为什么 TCP 这么复杂? 因为要保证可靠性, 同时又尽可能的提高性能.

  • 可靠性:校验和、序列号(按序到达)、确认应答、超时重发、连接管理、流量控制、拥塞控制
  • 传输效率:滑动窗口、快速重传、延迟应答、捎带应答

基于TCP的应用层协议:

  • HTTP
  • HTTPS
  • SSH
  • Telent
  • FTP
  • SMTP

对比TCP和UDP

TCP 是可靠连接, 那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点, 不能简单, 绝对的进行比较.我们需要根据实际的场景来选择合适的协议。

  • TCP 用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景
  • UDP 用于对高速传输和实时性要求较高的通信领域, 例如, 早期的 QQ, 视频传输等. 另外 UDP 可以用于广播;
  • 如果不知道使用什么传输层协议,那就优先考虑TCP

如何用UDP实现可靠传输(面试题目)

参考 TCP 的可靠性机制, 在应用层实现类似的逻辑;
比如:

  • 引入序列号,保证数据顺序
  • 引入确认应答,确保收到了数据
  • 引入超时重传, 如果隔一段时间没有应答, 就重发数据;
  • 引入窗口大小,控制流量
  • 等等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

法兰式满油阀SPF-125-12C、STF-125-12C

法兰式满油阀又名预充阀、充液阀,合金钢和球墨铸铁材质,体积小,易于拆卸,低压损,流量大,构造简单,耐久性佳,可直接装置于油缸盖侧,SPF-32-12C、STF-32-12C、SPF-50-12C、…

ZooKeeper中间件监控指标解读

监控易是一款功能全面的IT监控软件,能够实时监控各类IT资源和应用的状态,包括中间件、数据库、网络设备等。对于ZooKeeper这一重要的分布式协调服务中间件,监控易提供了详尽的监控指标,帮助用户全面了解ZooKeeper集群的运行状态。…

鸿蒙(API 12 Beta2版)NDK开发【使用Node-API接口进行异步任务开发】

使用Node-API接口进行异步任务开发 场景介绍 napi_create_async_work是Node-API接口之一,用于创建一个异步工作对象。可以在需要执行耗时操作的场景中使用,以避免阻塞主线程,确保应用程序的性能和响应性能。例如以下场景: 文件…

最新版Polyverse - Music Bundle Deal [06.2024],win和mac,支持intel和M1芯片

一。Polyverse插件套装 Polyverse - Music Bundle Deal 1.释放您的创作潜力 无论您是希望突破创作极限的音乐制作人,还是寻求新颖创新方式来增强混音的音频工程师,Polyverse 捆绑包交易都具有非凡的价值,可以帮助您将音乐提升到一个新的水平…

【数学建模】【优化算法】:【MATLAB】从【一维搜索】到】非线性方程】求解的综合解析

目录 第一章:一维搜索问题 黄金分割法 股票交易策略优化 总结: 第二章:线性规划 线性规划(Simplex 算法) 生产计划优化 总结: 第三章:无约束非线性优化问题 梯度下降法 神经网络训练…

Python中导入不同文件夹中的函数

1、代码举例:from Python_CodeFile.LDAP3.del_file.Get_Computer_Dn import get_computer_dn # 以上代码导入路径为:Python_CodeFile/LDAP3/del_file/Get_Computer_Dn.py 文件中的get_computer_dn函数。

传统放牧方式与北斗科技的碰撞:北三短报文头羊定位追踪器PD28守护放牧生活

在大草原的广袤天地中,放牧生活是蒙古族人民的传统之一。然而,除了美丽和自由,放牧生活也伴随着一些危险。以前由于科技落后,人工成本低,主要依靠人力去放牧,牧民放牧顶风踏雪走个几十公里都极为寻常。除了…

AI识别智能称重-收银系统源码

系统概况 专门为零售行业的连锁店量身打造的收银系统,适用于常规超市、生鲜超市、水果店、便利店、零食专卖店、服装店、母婴用品、农贸市场等类型的门店使用。同时线上线下数据打通,线下收银的数据与小程序私域商城中的数据完全同步,如商品…

【ROS 最简单教程 005/300】ROS + VSCode 开发环境快速搭建

VSCode 全称 Visual Studio Code,是微软出的一款轻量级代码编辑器,免费、开源而且功能强大 本篇将以最简单的方法引导基于 VSCode 的,超全面开发环境的搭建及相关配置完全不了解 ROS 编程的友友,建议先看 👉快速体验 指…

WIFI7在游戏领域引发的变革

随着无线技术的快速进步,游戏体验正变得愈加丰富、复杂和逼真。现在最新的WIFI 7技术将带来新的飞跃,不仅有望重新定义网络游戏的体验,还有可能彻底革新整个游戏产业。可以想象一下,在未来,游戏世界不再有延迟和连接中…

【嵌入式】一种基于串口命令的模块测试API模板

本文主要记录一种用于嵌入式开发中【模块测试】通用模板,使用 getopt_long()函数作为串口命令行解析的工具,从而进行测试代码逻辑的编写。 本文以ADC 和 uart 测试为例,介绍函数的使用以及测试代码的编写 【测试环境说明 】 本文是在 rt-thr…

一篇长文搭建AI大模型应用平台架构

在研究了6家知名公司如何部署生成式AI应用程序后,注意到它们的平台有很多相似之处。概述了生成式AI大模型应用平台的常见组件、它们的作用以及它们的实现方式。尽力保持架构的通用性,但某些应用程序可能会有所不同。 Generative AI大模型应用平台整体架…

数据集相关类代码回顾理解 | StratifiedShuffleSplit\transforms.ToTensor\Counter

【PyTorch】图像多分类项目 目录 StratifiedShuffleSplit transforms.ToTensor Counter StratifiedShuffleSplit sss StratifiedShuffleSplit(n_splits1, test_size0.2, random_state0) 创建StratifiedShuffleSplit对象,用于将数据集划分为训练集和测试集。 …

农业物联网气象站的工作原理

TH-NQ10农业物联网气象站是一款集成了物联网与气象技术的创新设备,它在现代农业中扮演着重要角色,为农业生产提供了精准、实时的气象数据支持。以下是对农业物联网气象站的详细介绍: 定义与特点 农业物联网气象站通过物联网技术将气象观测设…

详解校门外的树(树状数组)

前言 在看之前建议先看一下 【学习笔记】详解树状数组-CSDN博客 题目 思路 建立两个树状数组,维护左括号与右括号。 假设有一个长度为10的数轴,我们要将区间[ 2 , 5 ]中种树,这时,我们将 2 处放一个左括号 ” ( ” ,5处放一个 ” )” &…

负载均衡的作用、负载均衡常用处理方式、四层和七层负载均衡的区别、及配置方法

一、负载均衡的作用 解决服务器的高并发压力,提高应用程序的处理性能; 提供故障转移,实现高可用; 通过添加或减少服务器数量,增强网站的可扩展性; 在负载均衡器上进行过滤,可以提高系统的安…

FreeModbus学习——定时器

FreeModbus版本:1.6 协议栈初始化时会初始化定时器: eMBInit → eMBRTUInit → xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) 协议栈使能时会使能定时器: eMBEnable → pvMBFrameStartCur → eMBRTUStart → vMBPortTimersEnable 定时…

【Vulnhub系列】Vulnhub_Dr4g0n_b4ll 靶场渗透(原创)

【Vulnhub系列靶场】Vulnhub_Dr4g0n_b4ll靶场渗透 原文转载已经过授权 原文链接:Lusen的小窝 - 学无止尽,不进则退 (lusensec.github.io) 一、环境搭建 选择打开.ovf 文件 配置名称和路径 打开后调整网络连接模式为【NAT】即可 二、信息收集 1、主机…

MySQL安装教程(保姆级)

1. 首先要了解自己的计算机 打开设置——系统——系统信息 然后就可以知道自己计算机的类型了。 2. 下载MySQL 2.1. 来到MySQL官网 点击进入 我们下拉页面,可以找到DOWNLOADS 页面默认给咱们选择最新的版本,咱们不用,咱们尽量选一个稳定的版…

解决vscode+UE5中vscode无法识别头文件,无法函数无法跳转,也无法自动补全的问题。

一、概述 接上一条博客,虽然解决了报错的问题,但是实际上的问题却没有解决,无论我怎么点击,其都无法完成跳转,也无法完成自动补全的问题。 在网络上搜索了很多资料后,发现是在使用vscode时候UE5在vscode中的…