草庐IT

TCP的三个窗口:发送窗口swnd、接收窗口rwnd、拥塞窗口cwnd

林哥小站 2024-05-18 原文

在文章TCP滑动窗口协议与流量控制中,我们已经理解了滑动窗口(发送窗口swnd和接收窗口rwnd)。

在发送端TCP通过发送窗口提高分组报文的传输效率,同时TCP也要求发送端维护一个接收窗口(rwnd)以提供流量控制,注意接收窗口的值是由接收方计算出来,并通报给发送方后,让发送方用来计算出接收窗口后主动做流量发送控制的。

因为TCP是全双工通信,所以两边的主机同时都是发送方和接收方,所以两边的主机都同时维护了自己的滑动窗口(发送窗口swnd和接收窗口rwnd)。注意在不考虑拥塞控制等算法的情况下,发送窗口swnd和接收窗口rwnd就会退化成完全相等的同一个窗口。

通常TCP有三个窗口,接收窗口 rwnd (receive window),发送窗口swnd(send window),拥塞窗口cwnd(congestion window)。

拥塞避免(cwnd)发送方使用的流量控制,而滑动窗口(swnd, rwnd)是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估计,而后者则与接收方在该连接上的处理能力处理速度大小有关。

接收窗口 rwnd (receive window)

接收窗口rwnd使用图中的三个变量计算而来,即下图的下半个图的蓝色部分

1应用程序已经读走的最后一个分组报文的最后一个字节序号,定义为LastByteRead

2从网络中收到的最后一个分组报文的最后一个字节序号,定义为LastByteRecv

3提供的窗口,定义为RecvBuffer

接收方的接收窗口rwnd = RecvBuffer - [LastByteRecv - LastByteRead]。

发送窗口swnd(send window)

发送窗口swnd和rwnd有类似的计算方法,是指上图中,上半个图里的蓝色部分。

1未收到确认的第一个分组报文的前一个分组的最后一个字节序号,定义为LastByteAcked

2下一个可发送的分组报文的前一个报文的最后一个字节序号,定义为LastByteSent

3提供的窗口,定义为SendBuffer

发送方的窗口swnd的初始值为:由拥塞窗口cwnd和rwnd两者中取小值,swnd是一定会小于等于rwnd, 然后系统会用 LastByteSent - LastByteAcked <= rwnd来控制流量的发送。

在网络足够好,即cwnd足够大的情况下, 我们可以简单的认为 swnd = rwnd - (LastByteSent - LastByteAcked) , 真实可用的发送大小还取决于剩余可用发送缓冲区SendBuffer - (LastByteSent - LastByteAcked)的大小。

在接收方能力足够强,即rwnd足够大的情况下,swnd <= cwnd。

这个告诉我们在发送方发送能力足够大的情况下,网络的吞量取决于网络状况cwnd和接收方的接收能力rwnd),cwnd和rwnd二个值都是随着网络的状态和接收方接收能力的变化而动态变化的。

拥塞窗口cwnd(congestion window)。

拥塞窗口是TCP中设计的一种用于避免网络拥塞发生的机制。拥塞窗口的大小取决于网络的拥塞程度,并且动态变化。发送方通过保证自己的发送窗口小于等于拥塞窗口以避免网络拥塞的发生。

发送方控制拥塞窗口的原则是:网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。只要网络一出现拥塞,拥塞窗口就减少一些,以减少注入到网络中的分组数,避免网络拥塞。

cwnd是随着网络状态的变化面变化的,它的大小与TCP慢启动门限,拥塞避免算法,快重传算法和快恢复算法相关,具体cwnd的产生算法,我们可以再开篇来讲。

通过本文,大家可以理解TCP的这三个窗口,以及TCP如何通过这三个窗口进行流程控制。

有关TCP的三个窗口:发送窗口swnd、接收窗口rwnd、拥塞窗口cwnd的更多相关文章

  1. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  2. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

  3. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  4. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  5. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

  6. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  7. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  8. ruby - 如何理解 Ruby 中的发送者和接收者? - 2

    我很难理解Ruby中sender和receiver的实际含义。它们一般是什么意思?到目前为止,我只是将它们理解为方法调用和获取其返回值的调用。但是,我知道我的理解还远远不够。谁能给我一个Ruby中发送者和接收者的具体解释? 最佳答案 面向对象中的一个核心概念是消息传递和早期概念化,这在很大程度上借鉴了计算的Actor模型。艾伦·凯(AlanKay)创造了面向对象一词并发明了最早的OO语言之一SmallTalk,他拥有voicedregretatusingatermwhichputthefocusonobjectsinsteadofo

  9. ruby - 动态扩展现有方法或覆盖 ruby​​ 中的发送方法 - 2

    假设我们有A、B、C类。Adefself.inherited(sub)#metaprogramminggoeshere#takeclassthathasjustinheritedclassA#andforfooclassesinjectprepare_foo()as#firstlineofmethodthenrunrestofthecodeenddefprepare_foo#=>prepare_foo()neededhere#somecodeendendBprepare_foo()neededhere#somecodeendend如您所见,我正在尝试将foo_prepare()调用注入

  10. ruby-on-rails - 如何通过 POST 发送多个相同的键/参数? - 2

    如果我必须在一个HTTP请求中发送一堆post参数,所有这些参数都具有相同的名称,我该如何构建要发布的data对象?想象一个带有一些复选框的表单,它们都具有相同的name属性但具有不同的值(如果它们被选中):我想用ruby​​构建它(但它需要根据在表单上选择的内容动态创建):data={"color"=>"red","color"=>"green","color"=>"blue"}然后将数据发送到某个URL:Net::HTTP.post_form(url,data)我无法控制接收端,所以我必须发送它期望接收的参数。怎么办? 最佳答案

随机推荐