【TCP/IP详解 卷一:协议】TCP的小结

2023-11-19

前言:TCP学习的综述

在学习TCP/IP协议的大头:TCP协议 的过程中,遇到了很多机制和知识点,详解中更是用了足足8章的内容介绍它。
TCP协议作为 应用层 和 网络层 中间的 传输层协议,既要为下面的网络层协议保证连接的可靠性(IP协议)弥补不足,又要作为 应用层进程向网络层发送数据的中转站(作为多路复用/解复用器)。

这就使得我们在审视TCP这个协议的过程中,需要横向和纵向地看待TCP连接

  • 横向的连接:client 的 TCP 与 server 的 TCP。三握四挥,是 reliable 的体现。
  • 纵向的连接:网络层 和 应用层 之间联系的纽带,协助 应用层 向网络层 转递数据。

与此同时,在TCP的学习中,我们还需要解答TCP的相关问题:

reliable

TCP是如何保障连接的可靠性的?-超时重传的内容

Control

TCP是如何解决网络拥塞的?-各种机制:慢启动,拥塞避免,经受时延的ACK···
TCP是如何解决流量控制(目的:提高网络的利用率)的?-窗口机制:拥塞窗口,通告窗口···

我想,正是在 reliable 和 control 两部分,TCP下足了功夫。
保证 reliable 的目的是为了解决网络层协议的不足之处:解决数据的丢失重传问题,使得传输数据的连接变得更加可靠;而 control 的目的则是想办法使得传输的效率更高。两者相互影响:
比如我重发数据报的时候会不会造成网络的拥塞?我控制网络拥塞的时候会不会导致传输效率的低下?我要什么时候控制网络拥塞而不会过度控制 导致我的一些重要信息发送缓慢?我要什么时候发送数据报才不会造成更加严重的网络拥塞?

正是为了解决这些十分纠结的问题,TCP诞生了。正是它的伟大和不足,以及为了解决它的不足提出的各种各样的方法,使得它具有迷人的魅力。

本文不会过多的抠细节,是一篇对 TCP各部分的小结,试图阐述清楚它们之间的关系。

建议参考文章:TCP协议疑难杂症全景解析

第一部分:TCP是怎么建立连接的?-三握四挥

众所周知,TCP是通过 三次握手 和 四次挥手 来建立/终止一个 client-server TCP连接的。

三次握手 四次挥手

三次握手 建立起 TCP连接 的 reliable,分配初始序列号和资源,在相互确认之后开始数据的传输。有 主动打开(一般是client) 和 被动打开(一般是server)。
四次挥手,因为TCP连接是全双工的,数据可以在两个方向上进行传递,因此在关闭的时候需要必须单独终止两个方向的数据传输。有 主动关闭(一般是client) 和 被动关闭(一般是server)。

状态转移

既然有三握四挥的机制,那么在它进行的过程中,client端 和 server端 就有不同的状态,在SYN报文,FIN报文或者是ack的发送/接收,都会导致状态的转移。也就有了TCP状态转移图:

研究清楚这幅图是学习 TCP连接的建立与终止 的关键。

需要特别注意的是,在结束一个TCP连接的时候,client端有三种状态(FIN_WAIT1,FIN_WAIT2,TIME_WAIT),server端有两种状态(CLOSE_WAIT,LAST_ACK).

client端 的 TIME_WAIT状态(2MSL状态)

当发送端 接收到 接收端的 FIN,并发送最后一个ack之后,发送端从 FIN_WAIT2状态 进入 TIME_WAIT状态。
TCP数据报有一个 报文段最大生存时间MSL,它是任何报文段被丢弃前在网络内的最长时间。

设置2MSL状态的目的是为了防止以下状态:发送端发送的最后一个ack丢失。设置时间最长为 2MSL 的等待状态,保证接收端的定时器超时重传FIN,使得发送端重新发送最后一个ack。

如果说不这么做呢?
假如没有2MSL状态,服务器没有收到最后一个ack,向发送端重发一个FIN,此时发送端已经关闭,这个FIN有可能被丢失,有可能迟到。倘若发送端和接收端 重新使用同一个套接字/插口对(socket):目的端IP地址,源IP地址,目的端端口号,源端口号组成的组合 所确定的连接,那么如果说FIN迟到了,并到达发送端,有可能异常终止这条连接。
所以我们要求,在2MSL等待状态的时候,确定这条连接的插口对(socket)不能被使用,也就是说,不能用于建立新的连接。

复位

三种情况发送复位报文段:

  • 对方端口不存在
  • 异常关闭
  • 检查半打开连接

需要注意的是 第三种情况:一方异常关闭但是另外一方还不知道,这在之后的保活定时器(keep-alive)有提到。

第二部分:TCP是如何保证可靠性的?-TCP的超时机制与重传

TCP是如何保证数据传输的可靠性的?答曰重传定时器。
重传定时器,保证了发送方在定时器超时溢出且还没有收到对数据的确认的时候,重新发送数据报,并启动一些机制(数据报丢失很可能是因为网络拥塞,为了减缓网络拥塞,TCP提供了许多解决网络拥塞的方法,这里提到的是慢启动/拥塞避免)。

关于定时器时间的计算,采用了估计 往返时间RTT 和 重传时间RTO 的策略。
(1)如果超时没有接收到数据报,RTO 采用 指数退避 的方法更新。
(2)如果接收到了数据报,定时器首先跟踪往返时间RTT,然后根据公式来计算 RTO。公式利用了 均值偏差 和 RTT估计器 来减小计算RTO时因为网络时延等原因带来的误差。

重传定时器的设计有两个原则:一是 发送完如何一个报文,并长期收不到它的确认的时候,必须超时;二是 不能过早的超时:即超时的时间设置 不能和 测量的RTT 差太远。

对于定时器,RFC有以下四则规则:
(1)发送TCP分段时,如果还没有重传定时器开启,那么开启它。
(2)发送TCP分段时,如果已经有重传定时器开启,不再开启它。
(3)收到一个非冗余ACK时,如果有数据在传输中,重新开启重传定时器。
(4)收到一个非冗余ACK时,如果没有数据在传输中,则关闭重传定时器。

其中规则3是用于避免过早的重传。
也就是说,当发送端一次性发送多个数据报的时候,比如一次性发送 A B C D 四个数据报(暂且不考虑拥塞窗口和通告窗口),当 发送A 的时候,启动重传定时器,在收到 A的确认 的时候,重置 重传定时器。这样保证不会出现这样的情况:一次性发送完以上的四个数据报之后,发送端等待的是 对D数据报的确认,但是在定时器超时之前,除了比较早发送的 A B 发送方接收到了对它们的确认之外,并没有收到 C 和 D 的确认,这就导致了 不必要的重传。
大多数情况下,一个数据报测得的 往返时间RTT 约等于 重传时间。

第三部分:TCP是如何保证传输数据的 效率 ?-流量控制 避免网络拥塞

本节将看到,TCP对网络的流量控制,和避免网络拥塞的众多机制:
经受时延的确认(接收方) Nagle算法(发送方) 通告窗口(接收方) 拥塞窗口(发送方) 滑动窗口机制(接收方 & 发送方) 慢启动(发送方) 拥塞避免算法(发送方) 快速重传和快速恢复(发送方) 糊涂窗口综合症的解决方法(接收方 & 发送方)

一个死循环:网络拥塞 -> 数据报丢失 -> 重传 -> 网络拥塞 ···
TCP是怎么样解决这个死循环,并提高网络的效率的呢?

角度一:接收方 与 发送方

角度一:接收方TCP独有的 流量控制 和 避免网络拥塞 的机制与措施

  • (1)避免过多的ack造成 低速网络(如广域网) 的网络拥塞:经受时延的确认。
    联系:Nagle算法,避免糊涂窗口综合症的措施(防止小包)。
  • (2)避免接收方处理过慢,导致接收队列溢出数据丢失:通告窗口。
    联系:拥塞窗口,滑动窗口机制。
概要:

经受时延的确认/数据捎带ACK:通常TCP在收到数据的时候,并不马上发送对该数据的确认,相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送。绝大多数的时延为200ms。
在慢速网络 比如广域网上,过多的小包会造成一定的网络拥塞,从而导致数据报的丢失,效率低下。而如果 接收方TCP 并不采用此机制,即一接收到数据报就发送对它的确认ACK,无疑会造成小包数量的剧增,再加上服务器本来就要向发送方发送的数据,造成网络拥塞也就并不奇怪了。

通告窗口:接收方以一个比较慢的速率来处理接收的数据,而发送方以一个比较快的速率来发送数据,如果没有一个合理的机制来控制的话,势必会造成接收方接收队列的溢出,网络的拥塞以及数据的丢失。接收方提供的是 通告窗口,与 经受时延的ACK 或者是 数据 一起发送往发送方。

角度一:发送方TCP独有的 流量控制 和 避免网络拥塞 的机制与措施

  • (1)慢启动 ssthresh 拥塞避免
    联系:滑动窗口机制,通告窗口。
  • (2)拥塞窗口 -慢启动提供:概要中与(1)一起
    联系:滑动窗口机制,通告窗口。
  • (3)快速重传,快速恢复算法
    联系:慢启动,拥塞避免等。
  • (4)Nagle算法 防止小包
    联系:经受时延的ACK,避免糊涂窗口综合症的措施。
概要:注意慢启动和拥塞避免维持的两个变量 ssthresh 与 cwnd

慢启动:如果发送方一开始就向接收方发送多个报文段,直到达到接收方的通告窗口为止,很容易造成中间路由器的缓存溢出,耗尽存储启动空间,从而造成网络拥塞。
慢启动的工作方法是观察到 新分组进入网络的速率 = 另外一端确认分组的速率来进行工作的。
慢启动为发送方增添了:拥塞窗口,初始值为1,每接收到一个ack就增加1。发送数据报的数量取决于 min{拥塞窗口,通告窗口}。

但是,慢启动一点也不慢,它的拥塞窗口的增长方式是 指数型的。这样到了后期 拥塞窗口 必然会超过 通告窗口,也就达不到控制的效果了。
于是乎,我们引入了 拥塞避免算法。

拥塞避免算法:当拥塞窗口增大到一定程度的时候,我们采用拥塞避免算法,而不是慢启动。慢启动和拥塞避免算法之间的界限 我们称之为 ssthresh(16个报文段,也就是65535字节,拥塞窗口的大小)。
拥塞窗口算法的实现:每收到一个ack,拥塞窗口增加1/cwnd,这是一种加性增长,放缓了慢启动的指数增长。

慢启动和拥塞避免的工作过程:教材P235.

慢启动与拥塞避免的可视化描述:

快速重传,快速恢复算法:我们并不知道 一个重复的ACK是由一个丢失报文段引起的,还是由于仅仅出现了几个报文段的重新排序,因此我们必须等待少量的重复ACK的到来。如果一连串收到三个重复的ACK,那么基本可以确定是数据报丢失引起的,那么此时网络很有可能已经拥塞,需要采取 慢启动或者是拥塞避免的措施 来控制网络拥塞。
在连续收到三个重复的ACK之后,我们不用等到定时器溢出,直接进行重传,这就是快速重传算法。接下来执行的 并不是 慢启动 而是 拥塞避免,这就是快速恢复算法。
我们不想进入慢启动的原因是因为,在收发两端仍然有流动的数据,我们并不想使用慢启动,从而造成数据流的突然减少。

快速重传 快速恢复算法的工作过程:教材P237.

Nagle算法:发送方用于防止小包的措施,具体原因与 接收方TCP的 经受时延的ACK 一样:避免慢速网络的网络拥塞。
该算法要求一个TCP连接上 最多只能有一个 未被确认的小分组,这导致了发送方数据的积累:在确认到达之前不允许发送小分组,相反TCP积累这些小分组,并在确认到达的时候“一股脑儿”以一个数据报的形式发送出去。
优越之处在于:确认到达的越快,数据发送的也就越快。它是自适应的。

发送方与接收方 共有的 防止网络拥塞 和 控制流量 的措施

  • 滑动窗口机制:发送方TCP 的 拥塞窗口 与 接收方TCP 的 通告窗口 的共同作用。作用于发送端。
  • 糊涂窗口综合症 与 发送方TCP 的 Nagle算法 和 接收方TCP 的 经受时延的ACK 有直接的关系。
概要:

首先谈谈 滑动窗口机制,它的可视化表示如下图:

接收方 鉴于自身接收数据的快慢,向发送方提供 通告窗口,以实现对发送端发送流量的控制,这个通告窗口就是上图中的 提供的窗口。
发送方 根据接收到数据报的情况,基于避免网络拥塞的慢启动算法,提供了拥塞窗口,即上图中 发送但未被确认。

当发送方发送的数据 被成功确认的时候,滑动窗口的左沿向右移动;同时根据接收方新发送的通告窗口,右沿也向右移动。移动的距离是由 返回的确认号 与 发送端缓存的 目前第一个尚未被确认的数据报的初始序号 的差值所决定。

滑动窗口机制,即体现了 接收方根据自身情况对发送方的流量控制(通过通告窗口),避免了发送方一次性发送过多的数据导致读取数据缓慢的接收方缓存溢出;又体现了 发送方TCP对网络拥塞的监视,以及避免拥塞的策略(通过慢启动算法 提供的 拥塞窗口)。

但是,接收方对发送方的流量控制 同时也会带来一些不好的东西,就是我们接下来要引述的 糊涂窗口综合症 了。
由于接收方处理数据十分缓慢,往往在一个数据报往返时间RTT内处理不了多少数据,这就导致了接收端经常会通告一些小窗口,这是我们不希望看到的:在前面有提到,过多的小包会加剧慢速网络的网络拥塞程度。这就是 糊涂窗口综合症。

由于接收方可以通告一个小的窗口,发送方也可以发送小的数据,因此 避免糊涂窗口综合症的对策也是从 对发送方 和 对接收方 两个方面着手的:

(1)对发送方(在满足以下条件之一的情况下发送数据)

  • 可以发送一个满长度的数据报,即一个MSS长度的数据报。
  • 可以发送至少是通告窗口一半的数据
  • 可以发送任何数据但是不希望接收ACK(前面还有未确认的报文) 或者该连接上不能使用Nagle算法。

(2)对接收方

  • 接收方不通告小的窗口(特例:教材P249,防止滑动窗口右沿左移),并且一般不通告比目前的接收状况 即窗口 更大的大小。除非 接收方应用进程接收了MSS大小的数据,或者处理了接收方一半缓存大小的数据。

糊涂窗口综合症的解决方法,与发送方TCP的Nagle算法,和接收方的经受时延的ack,是TCP用于避免慢速网络(WAN)网络拥塞的策略。

角度小结:How to control?

通过角度一对于发送方和接收方各自以及共有的流量控制及避免网络拥塞的策略进行了一个归纳。

有我们开头的四个问题:

  • TCP是怎么样知道发生了数据报丢失?
  • TCP怎么样处理网络拥塞?
  • TCP怎么样控制重传的时间 从而不会引起过度的不必要的重传?
  • TCP怎么样均衡 控制网络拥塞 以及 传输效率?

以及这个死循环:网络拥塞 -> 数据报丢失 -> 重传
这个死循环很大程度的导致了传输数据效率的低下,于是乎,TCP必然要采取一定的措施来制止这个死循环的发生。

那么我们把这四个问题 和 这个死循环结合起来,根据上文的内容来解答他们。

(1)网络拥塞,既然TCP知道可能会出现网络拥塞,那么接收方和发送方的TCP肯定要想办法避免它和解决它。
避免它:慢启动算法 和 拥塞避免算法,慢启动所提供的拥塞窗口;针对慢速网络:Nagle算法,经受时延的ack,避免糊涂窗口综合症的措施。
解决它:当拥塞发生的时候,我们希望降低分组进入网络的传输速率,拥塞避免算法起到了很好的处理丢失分组的方法,在教材的P235详细说明了拥塞避免算法在拥塞发生的时候所采取的措施(启用慢启动,设置ssthresh等)。

(2)数据报丢失,网络拥塞造成了数据报丢失,发送方怎么样知道数据报丢失?
处理数据报丢失的方法是 (3)重传,那么发送方什么时候重传不会造成重传风暴 导致网络拥塞?
TCP 在 发送数据的效率 和 减缓网络拥塞 是怎么样均衡的?

发送方是如何知道数据报丢失的?
-重传定时器超时,或者是发送方接收到了三个重复的ack;前者重发数据报并利用指数退避更新RTO,后者立即重发数据报,进入快速重传和快速恢复。
准确的来说,重传定时器超时所估计的网络拥塞比接受到的三个重复的ack所估计的网络拥塞更加严重:收到三个重复的ack有可能是因为数据报的错序导致的,说明后面的数据报接收方有收到,就进入快速重传快速恢复状态;而重传定时器超时估计起来就严重的多了,网络拥塞程度已经严重到丢失大量数据的阶段了,因此必须使发送方重新进入调整网络拥塞的状态:慢启动或者拥塞避免。

什么时候重传 不会造成进一步的拥塞?
-控制重传时间的 是重传定时器,TCP利用对往返时间RTT的测量跟踪路由器和网络流量的变化,利用往返时间RTT的估计器以及均值偏差来确定重传的时间,最大程度的降低了估计的误差,并且利用RFC定义的重传定时器的四个原则保证了它不会过早的重传,从而造成不必要的重传。

TCP是怎么样均衡控制网络拥塞 和 传输效率的?
-利用滑动窗口机制,以及慢启动对拥塞窗口的“指数型增长” 和 拥塞避免对拥塞窗口的“加性增长”,尽可能的利用带宽,同时也减小网络拥塞发生的可能。
滑动窗口机制的拥塞窗口是发送方根据其对网络拥塞的估计(利用RTT) 避免中间路由缓存的溢出 所采取的流量控制措施;而通告窗口则是 接收方 根据自身进程接收数据的快慢,以及在该连接上可用缓存的大小,采取的流量控制措施。
与此同时,避免网络拥塞的 慢启动 和 拥塞避免 也提供了利用网络带宽 提高网络效率的方法:每接收到一个ack,就增加拥塞窗口的大小。
这样,均衡地控制了网络拥塞 也保证了一定的传输效率。

慢启动和拥塞避免 是避免网络拥塞,解决网络拥塞的方法,它们作用于拥塞窗口,使在不同的网络条件下(拥塞或者不拥塞)尽可能的利用带宽。

这就是TCP中的control,内容既复杂又相互联系,但是需要抓住本质的两点来分析:1)控制流量,避免网络拥塞 2)控制传输数据的效率

To improve is to change, to be perfect is to change often.




https://www.cnblogs.com/qq952693358/p/5796520.html



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【TCP/IP详解 卷一:协议】TCP的小结 的相关文章

  • 有没有办法让 YouTube 的所有 IP 地址都被 Windows 防火墙阻止?

    我想编写自己的防分心工具 我不能 不想使用主机文件 https en wikipedia org wiki Hosts file 或第三方应用程序 使用时IPsec https en wikipedia org wiki IPsec or
  • 为什么在数据包输入时 skb_buffer 需要跳过 20 个字节才能读取传输缓冲区?

    我正在 Linux 中编写一个网络模块 我发现只有在从 skb 缓冲区跳过 20 个字节后才能提取 tcp 标头 即使 API 是 skb transport header 其背后的原因是什么 有人可以详细解释一下吗 传出数据包不需要同样的
  • Node.js 找不到模块“tcp”

    节点在以下行崩溃 var tcp require tcp 错误文本 node js 201 throw e process nextTick error or error event on first tick Error Cannot f
  • Socat未关闭tcp连接

    I use socat 1 7 3 1 r0并在alpine 3 3linux服务器 socat d d d PTY link dev ttyFOOBAR echo 0 raw unlink close 0 TCP LISTEN 7000
  • Android TCP 连接最佳实践

    我正在开发一个需要 TCP 连接到 TCP 服务器的 Android 应用程序 用 Node js 编写 我的 Android TCP 客户端正在工作 可以来回发送消息 我的具体问题是 在 Android 中处理与服务器的 TCP 连接的最
  • Scapy 不需要的 RST TCP 数据包

    为了理解TCP是如何工作的 我尝试伪造自己的TCP SYN SYN ACK ACK 基于教程 http www thice nl creating ack get packets with scapy http www thice nl c
  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • C# - 从客户端检查 TCP/IP 套接字状态

    我想为我的 TCP IP 客户端类提供 CheckConnection 函数 以便我可以检查是否发生了错误 我自己的客户端断开连接 服务器断开连接 服务器卡住等 我有类似的东西 bool isConnectionActive false i
  • jQuery JSON 请求得到“200 OK”答案,但没有内容

    我正在使用 jQuery 通过访问者的 IP 地址获取其位置 有一项很棒的服务叫做免费地理IP http freegeoip appspot com 我需要做的就是在 URL 末尾添加 json 或 xml 然后添加 IP 地址 它将返回所
  • Python套接字模块:Recv()数据响应被切断

    解释 我目前正在尝试使用 python 脚本控制智能电源板 为了实现这一点 我使用了带有套接字模块的 TCP 连接 大约 75 的情况下 我会得到我正在寻找的响应 数据 并且一切都运行良好 然而 大约 25 的情况下 响应会以完全相同的长度
  • 在 Golang Server 中接受持久的 tcp 连接

    我正在尝试使用 Go 并且想创建一个 TCP 服务器 我可以通过 telnet 访问该服务器 发送命令并接收响应 const CONN HOST localhost CONN PORT 3333 CONN TYPE tcp func mai
  • 如何在Linux中打开端口[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我已经安装了 Web 应用程序 该应用程序在 RHEL centOS 上的端口 8080 上运行 我只能通过命令行访问该机器 我尝试从我的
  • 为什么turn服务器不支持tcp连接?

    我是 WebRTC 新手 我需要为我的 webrtc 应用程序配置我自己的 Turn 服务器 我使用以下命令安装了我的转弯服务器 apt get install coturn 我只需要通过 tcp 运行转变服务器 它不必使用 UDP 进行任
  • 自动打开命名管道和 tcp\ip

    我正在安装一个需要修改 SQL Server 的新产品 具体来说 启用 tcp ip 并打开命名管道 我知道如何手动完成 我想要的是一种通过 SQL 或 C 代码为新客户自动化执行此操作的方法 我希望有任何关于正确方向的建议 您可以使用 C
  • 是否可以找到哪个用户位于 localhost TCP 连接的另一端?

    这是一个编程问题 但它是 Linux Unix 特定的 如果我从本地主机获得 TCP 连接 是否有一种简单的方法可以告诉哪个用户在 C 程序内建立了连接而无需 shell 我知道这对于 Unix 域套接字来说并不太难 我已经知道远程 IP
  • 将 PostgreSQL 中的 IP 地址转换为整数?

    有没有一个查询可以完成这个任务 例如 给定一个条目 216 55 82 34 我想用 分割字符串 并应用等式 IP 号 16777216 w 65536 x 256 y z 其中 IP 地址 w x y z 仅通过查询就可以实现这一点吗 您
  • 分配 TCP/IP 端口供内部应用程序使用

    我编写了一个由 Windows 服务托管的 WCF 服务 它需要侦听已知的 TCP IP 端口 我可以在什么范围内安全地分配端口供我的组织内使用 该端口将嵌入到服务和使用该服务的客户端的配置文件中 端口 0 1023 是众所周知的端口 由
  • 触发“对等方重置连接”

    我想测试当发生 对等方重置连接 错误时我们的应用程序 嵌入式 ftp 服务器 中发生的日志记录 这个帖子 https stackoverflow com questions 1434451 connection reset by peer很
  • 如果其中一台机器死机,TCP 连接如何终止?

    如果两个主机 A 和 B 之间建立了 TCP 连接 假设主机 A 已向主机 B 发送了 5 个八位字节 然后主机 B 崩溃了 由于未知原因 主机 A 将等待确认 但如果没有收到确认 将重新发送八位字节并减小发送者窗口大小 这将重复几次 直到
  • PHP中如何识别服务器IP地址

    PHP中如何识别服务器IP地址 对于服务器 ip 来说是这样的 SERVER SERVER ADDR 这是港口的 SERVER SERVER PORT

随机推荐

  • Basic Level 1018 锤子剪刀布 (20分)

    题目 大家应该都会玩 锤子剪刀布 的游戏 两人同时给出手势 胜负规则如图所示 现给出两人的交锋记录 请统计双方的胜 平 负次数 并且给出双方分别出什么手势的胜算最大 输入格式 输入第 1 行给出正整数 N 1 0 5
  • c++ 学习之set和multiset区别

    区别 set不允许有重复的值 multiset可以有重复的值 代码示例 include
  • 技术干货分享,万字长文深度解读机器翻译

    编者按 在 机器翻译是如何炼成的 上 的文章中 我们回顾了机器翻译的发展史 在本篇文章中 我们将分享机器翻译系统的理论算法和技术实践 讲解神经机器翻译具体是如何炼成的 读完本文 您将了解 神经机器翻译模型如何进化并发展成令NLP研究者万众瞩
  • CF、SF、OF、ZF标志位

    没学汇编 这种题我真是做一道错一道 OF overflow flag 溢出标志位 溢出标志位 OF 1 表示带符号整数运算时结果发生溢出 对于无符号整数运算 OF没有意义 对于有符号数的溢出判断方式有 1 采用一位符号位 思想为 或 则为溢
  • 利用dbnet分割条形码与文字(代码+模型)+知识蒸馏+tensorrt推理+利用pyzbar和zxing进行条形码解析

    一 DBnet 1 代码链接 分割条形码与文字代码 github链接 GitHub zonghaofan dbnet torch you can use dbnet to detect word or bar code Knowledge
  • CocosCreator之KUOKUO带你做小小赛车-摄像机跟随

    本次引擎2 0 5 编辑工具VSCode 目标 小小赛车 先亮素材 很简单 就两个 爱给网中的赛道 以及一个小车 好了 让我们新建工程然后把赛道放进去 调整方向与大小 然后把小车拖上去 这样 我是把赛道放大了2倍 旋转了90度 拖一拖位置
  • onclick传参使用function()

    对于有需要传参的按钮 需要按照以下的方式进行 直接上代码
  • 9、Linux(Ubuntu 18)安装Redis以及C操作Redis

    扩展知识 头文件搜索 Linux中库的头文件 首先include有两种写法 一种是 include 另一种是 include xxx 这两种写法的区别是 include xxx 会首先在当前目录下搜索头文件 不递归 如果找不到的话再去系统目
  • 3分钟玩转:ES6 模块化

    ES6 模块 ES6 使用 export 和 import 导出和导入模块 导出模块 一个模块就是一个独立的 JS 文件 该文件内的变量外部无法获取 若希望能让外部获取模块内的变量 则要用 export 关键字暴露变量 分别暴露 命名行内导
  • Windows11右键菜单太烦人,简单几步即可恢复旧版完整菜单

    Windows 11已经推出一段时间了 相比Windows 10 界面确实美观了不少 同时也有很多新的设计 但是并不是每个人都能很快适应这种新设计 被广泛吐槽的一点就是右键菜单的改变 增加了显示更多选项 原来的很多右键选项被隐藏起来了 原本
  • tkinter 的界面美化库:ttkbootstrap 使用教程

    嗨害大家好鸭 我是芝士 tkbootstrap 是一个基于 tkinter 的界面美化库 使用这个工具可以开发出类似前端 bootstrap 风格的 kinter 桌面程序 如果会 tkinter 学习起来就会非常简单 如果不会的话只要先花
  • opencv python contours结构

    opencv python contours结构 经常需要构造 如果没记住内部具体结构 需要到网上处找 且找不到 就要自己findcontours然后打印出来 比较麻烦 contours的结构 比如一个box有xmin ymin xmax
  • 今天发现一个好网站 http://www.phpv.net/

    该网站的空间速度快 资料丰富 容易搜索 更新快 爽
  • 运维之道

    方法一 rc local 1 由于在centos7中 etc rc d rc local的权限被降低了 所以需要赋予其可执行权 chmod x etc rc d rc local 2 赋予脚本可执行权限 假设 opt script auto
  • pytorch训练error

    问题一 在pytorch上训练分割模型时 出现cuda runtime error 59 device side assert triggered at xxx 解决办法 通过CUDA LAUNCH BLOCKING 1 python3 m
  • python----小数点精度控制round()

    python版本也会影响结果 python2把x四舍五入为远离0的最近倍数 如round 0 5 1 round 0 5 1 python3则会把x四舍五入为最近的偶数倍数 如round 0 5 0 round 1 5 2 0 round
  • 查看解决inode使用率100%的问题

    今天登录后端服务器查看 发现程序报错日志中存在磁盘空间不足的情况 df h后发现磁盘空间充足 df ih发现 app分区inode使用率100 开始查找原因 进到 app 下 然后 for i in do echo i find i wc
  • hashMap常见的问题解答

    1 HashMap的数据结构 hashmap采取数组 链表的数据结构 在遇到哈希冲突的时候采用链表结构来解决哈希冲突 jdk1 8后分成了两种情况 bucket中元素个数大于8的时候 自动转换为红黑树的结构 目的是因为链表的查询速度比较慢
  • vue+element table 合并列

    vue element table 合并列
  • 【TCP/IP详解 卷一:协议】TCP的小结

    前言 TCP学习的综述 在学习TCP IP协议的大头 TCP协议 的过程中 遇到了很多机制和知识点 详解中更是用了足足8章的内容介绍它 TCP协议作为 应用层 和 网络层 中间的 传输层协议 既要为下面的网络层协议保证连接的可靠性 IP协议