- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题是我最近几天问过的另外两个问题的结果。
我正在创建一个新问题,因为我认为这与我对如何控制发送/接收流程的理解中的“下一步”有关,而我尚未得到完整的答案。
其他相关问题是:
An IOCP documentation interpretation question - buffer ownership ambiguity
Non-blocking TCP buffer issues
总之,我正在使用Windows I / O完成端口。
我有几个线程处理来自完成端口的通知。
我相信这个问题是与平台无关的,并且将具有与在* nix,* BSD,Solaris系统上执行相同操作一样的答案。
因此,我需要拥有自己的流量控制系统。精细。
所以我发送了很多。我如何知道何时开始排队发送,因为接收方限制为X数量?
让我们举个例子(最接近我的问题):FTP协议。
我有两个服务器;一个在100Mb链路上,另一个在10Mb链路上。
我命令一个100Mb的文件发送到另一个(10Mb链接的文件)一个1GB的文件。它的平均传输速率为1.25MB / s。
发送方(100Mb链接的发送方)如何知道何时暂停发送,因此较慢的发送方不会被淹没? (在这种情况下,“待发送”队列是硬盘上的实际文件)。
另一种询问方式:
我可以从远端收到“保留您的发送”通知吗?它是内置在TCP中还是需要我执行的所谓“可靠网络协议”?
我当然可以将发送限制为固定的字节数,但这对我来说听起来并不正确。
再说一次,我有一个循环,其中有许多发送到远程服务器的循环,在某个时刻,我将不得不确定是否应该对发送进行排队,或者可以将其传递给传输层(TCP)。
我怎么做?你会怎么做?当然,当我从IOCP收到完成发送的通知时,我将发出其他挂起的发送,这很清楚。
与此相关的另一个设计问题:
由于我要在发送队列中使用自定义缓冲区,并且在到达“发送完成”通知后,这些缓冲区将被释放以供重用(因此不使用“ delete”关键字),因此,我必须使用在那个缓冲池上的相互排斥。
使用互斥锁会使事情变慢,所以我一直在想;为什么每个线程都没有自己的缓冲池,因此至少在获取发送操作所需的缓冲区时访问它就不需要互斥体,因为它仅属于该线程。
缓冲池位于线程本地存储(TLS)级别。
没有相互池意味着没有锁,意味着更快的操作BUT也意味着应用程序使用了更多的内存,因为即使一个线程已经分配了1000个缓冲区,另一个正在发送并且需要1000个缓冲区来发送内容的线程也需要分配这些都是自己的。
另一个问题:
假设我在“待发送”队列中有缓冲区A,B,C。
然后,我收到一个完成通知,告诉我接收者从15个字节中提取了10个。我应该从缓冲区的相对偏移量重新发送,还是由TCP为我处理,即完成发送?而且,如果可以的话,我可以确保该缓冲区是队列中“下一步要发送”的缓冲区吗,还是例如缓冲区B?
这是一个很长的问题,我希望没有人受到伤害(:
我很乐意看到有人花时间在这里回答。我保证我会为他加倍投票! (:
谢谢你们!
最佳答案
首先:我将作为单独的问题提出这个问题。您更有可能以这种方式获得答案。
我已经在我的博客中谈到了大部分内容:http://www.lenholgate.com,但是既然您已经给我发送了电子邮件,说您已经阅读了我的博客,那么您知道...
TCP流控制问题是这样的,因为您要发布异步写入,并且这些异步写入都将使用资源,直到它们完成为止(请参见here)。在写挂起期间,需要注意各种资源使用问题,而使用数据缓冲区是其中最不重要的问题。您还将用完一些非页面缓冲的池,这是一种有限的资源(尽管在Vista和更高版本中,可用空间要比以前的操作系统多得多),而且在写操作期间还将页面锁定在内存中,并且操作系统可以锁定的页面总数的限制。请注意,非页面缓冲池的使用情况和页面锁定问题在任何地方都没有得到很好的记录,但是一旦您碰到它们,就会开始看到ENOBUFS写入失败。
由于这些问题,未控制的写入数量不受控制是不明智的。如果您要发送大量数据,并且没有应用程序级别的流控制,则需要注意的是,如果发送数据的速度快于连接另一端可以处理的速度,或者快于链接速度,然后由于TCP流控制和窗口问题,您的写操作将花费更长的时间,因此您将开始消耗大量上述资源。阻塞套接字代码不会带来这些问题,因为当TCP堆栈由于流控制问题而无法再写入时,写入调用只会阻塞。使用异步写入,写入完成,然后挂起。使用阻塞代码,阻塞将为您处理流控制。使用异步写入,您可能会继续循环运行,并且越来越多的数据正等待TCP堆栈发送...
无论如何,因此,对于Windows上的异步I / O,您应该始终具有某种形式的显式流控制。因此,您可以使用ACK将应用程序级流控制添加到协议中,以便知道数据何时到达另一端,并且一次只能允许一定数量的未完成交易,或者如果您不能添加到在应用程序级别协议中,您可以使用写入完成来驱动事物。诀窍是允许每个连接具有一定数量的未完成写入完成,并在达到极限后将数据排队(或只是不生成数据)。然后,当每个写入完成时,您可以生成一个新的写入。
恕我直言,关于合并数据缓冲区的问题是您现在的过早优化。到系统正常运行的位置,并且已经对系统进行了概要分析,并发现缓冲池上的争用是最重要的热点,然后解决这个问题。我发现每个线程的缓冲池不能很好地工作,因为线程之间的分配和释放的分布往往不如您需要的那样平衡。我已经在博客中谈到了更多内容:http://www.lenholgate.com/blog/2010/05/performance-comparisons-for-recent-code-changes.html
关于部分写入完成(您发送100个字节,然后返回完成并说您只发送了95个)的问题实际上在IMHO中不是问题。如果您到达这个位置并拥有多个未完成的写操作,那么您将无能为力,随后的写操作可能会正常工作,并且您期望发送的字节会丢失;但是a)我从来没有见过这种情况发生,除非您已经遇到了上面我详细介绍的资源问题,并且b)如果您已经在该连接上发布了更多写入信息,那么您将无能为力,因此只需中止该连接-请注意,这是为什么我总是将网络系统配置在将要运行的硬件上,并且我倾向于在我的代码中设置限制,以防止曾经达到操作系统资源限制(在Vista之前的操作系统上,不良的驱动程序通常会蓝屏,如果可以的话)不要使用非分页池,因此如果您不注意这些细节,可以放下一个盒子。
请下次再回答其他问题。
关于networking - 使用“待发送”队列和其他设计问题限制TCP发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3034047/
我正在使用 voip 推送通知制作 ios 应用程序。 我想从 Node js 发送 voip 推送通知,但不是很好。 我阅读了本教程 CallKit iOS Swift Tutorial for V
我编写了一个服务器,当浏览器尝试连接到某些站点时,它会检查黑名单并发回 404,但是当我调用 send() 时没有错误,但消息不会出现在网络上浏览器,除非我关闭连接? 有什么建议吗? 接受来自浏览器的
#include int main() { char c = getchar(); //EOF (ctrl + d ) while( ( c = getchar() ) != '?'
我正在尝试使用MailMessage对象通过PowerShell发送电子邮件。该脚本使用Import-CSV来使用文件,然后在电子邮件正文中使用ConvertTo-HTML。由于我要发送的电子邮件客户
我需要创建一个脚本,每 30 秒对网络流量进行一次采样并存储发送/接收的字节。该数据随后用于绘制图形。我编写了一个在 Windows 2012 上完美运行的程序,但我意识到某些 cmdlet 在以前的
我正在运行“autoit3.chm”文件。当它运行时,我想发送一个向下键箭头,但它不起作用: $file = FileGetShortName("C:\Users\PHSD100-SIC\Deskto
当我使用网络浏览器测试我的程序时,我可以很好地写入套接字/FD,所以我决定循环它并在连接中途切断连接,我发现了一个问题。 send() 能够在套接字不可用时关闭整个程序。我认为问题在于该程序陷入了第
我正在运行“autoit3.chm”文件。当它运行时,我想发送一个向下键箭头,但它不起作用: $file = FileGetShortName("C:\Users\PHSD100-SIC\Deskto
所以我试图向自己发送数据并接收数据然后打印它,现在我已经测试了一段时间,我注意到它没有发送任何东西,事实上,也许它是,但我没有正确接收它,我需要这方面的帮助。 这就是我用来发送数据的
问题:开发人员创建自己的序列化格式有多常见?具体来说,我使用 java 本质上将对象作为一个巨大的字符串发送,并用标记来分隔变量。 我的逻辑:我选择这个是因为它几乎消除了语言依赖性(忽略java的修改
我必须在 Linux 上编写一个应用程序,该应用程序需要与具有自定义以太网类型的设备进行通信。甚至在如何编写这样的应用程序中也有很多解决方案。一个缺点是需要 root 访问权限(AFAIK)。之后释放
我有一个包含三个单选按钮选项的表单。我需要将表单数据提交到另一个文件,但由于某种原因,发送的数据包含所选单选按钮的值“on”,而不是 value 属性的值。 我尝试通过 post() 函数手动操作和发
基本上我想实现这样的目标: Process 1 Thread 1 Receive X from process 2 Thread 2 Receive Y from proces
我目前正在 Google App Engine 上开发一个系统,对它还很陌生,我正在使用 Java 平台进行开发。我在 servlet 之间发送 session 对象时遇到问题。我已经在 appeng
当我尝试将“this”(触发的元素)作为参数发送给函数时,函数收到“Object[Document build.php]”作为参数,而不是触发的元素。请让我知道我的错误: function set(a
我正在寻找让我的应用响应联系人 > 发送的魔法咒语。我希望能够接收联系人的 URI 以便检索联系人。谁有 list 过滤器/代码 fragment 吗? 最佳答案 我没有睾丸,但您可以尝试基于 ACT
关于我心爱的套接字的另一个问题。我先解释一下我的情况。之后我会告诉你是什么困扰着我。 我有一个客户端和一个服务器。这两个应用程序都是用 C++ 编写的,实现了 winsock2。连接通过 TCP 和
我看到了这篇文章 http://www.eskimo.com/~scs/cclass/int/sx5.html 但这部分让我感到困惑:如果我们已经使用 send_array 或 send_array_
我对这行代码有疑问。我必须将一个数据包带到一个端口并重新发送到接口(interface)(例如:eth0)。我的程序成功地从端口获取数据包,但是当我重新发送(使用 send())到接口(interfa
我正在尝试编写一个 X11 输入驱动程序,它可以使用我的 Android 手机上的触摸屏来移动和单击鼠标。我可以正常移动鼠标,但我无法让应用程序正确识别点击。我当前的代码位于 https://gist
我是一名优秀的程序员,十分优秀!