当前位置:  开发笔记 > 前端 > 正文

在同一个套接字上可以进行多少异步套接字请求?

如何解决《在同一个套接字上可以进行多少异步套接字请求?》经验,为你挑选了1个好方法。

当我在套接字上调用BeginSend时,我传递一个委托,当发送数据时,该代理将被调用(由不同的线程).

如果我在第一次调用BeginSend而第一次尚未"回调"时会发生什么?

发送数据的正确行为是什么?做BeginSend,并在回调时做EndSend并开始另一个发送?或者让多个BeginSends同时工作真的很明智吗?

这是MSDN上的BeginSend页面,它没有给出这个问题的答案:BeginSend msdn



1> Len Holgate..:

正如OKW所说,多个待处理的BeginSend呼叫都可以正常工作.你可能需要记住一些事情.

首先,如果这是一个TCP套接字,那么这仍然是来自对等的单个数据流.

其次,如果所有BeginSend调用都发生在同一个线程上,那么结果将是对等体按调用顺序接收数据.如果您的BeginSend呼叫来自不同的线程,则数据可以按任何顺序到达,因为每个发送之间可能存在竞争条件.这对您来说可能或不重要(取决于您是否在每次发送时发送离散的完整消息).

第三,如果您使用TCP并且发送速度超过套接字另一端的代码可以接收,那么您可以填充TCP窗口,TCP堆栈将开始对您的数据流执行流控制.如果你继续发出BeginSend调用,那么你最终可能会因为服务器上的TCP堆栈将要发送的数据排队等待你的回调需要更长和更长时间而被调用(只有在数据发送后才能获得回调和TCP基于窗口的流控制将阻止在TCP窗口不再"满"之前发送新数据;即,对等体已经发送了针对某些数据的ACK in flight.

然后,您可能会陷入无法控制的方式在发送计算机上耗尽资源的情况(您发出BeginSend并且不知道它何时完成,并且每个发送都使用内存用于正在发送的缓冲区并且可能non-paged pool在Winsock代码中关闭... Non-paged pool是一个系统范围的资源,在Vista之前的操作系统上是非常稀缺的,如果non-paged pool是低或耗尽,一些表现不佳的驱动程序可以蓝屏.此外,你还可以将内存页锁定到内存中,还有另一个系统限制锁定的内存页数.

由于这些问题,通常最好实现自己的协议级别流量控制,该控制可以限制BeginSend任何时候可以挂起的呼叫数量(可能使用协议级别ACK)或使用TCP窗口流量控制并使用完成待发送以发出新发送,您可以将数据排队以在您自己的内存中发送,并完全控制所使用的资源以及如果排队"太多"数据时所执行的操作.有关详细信息,请参阅我的博客文章:http://www.serverframework.com/asynchronousevents/2011/06/tcp-flow-control-and-asynchronous-writes.html

看到这个回复:当tcp/udp服务器的发布速度超过客户端消耗时会发生什么?有关TCP窗口流控制的更多信息以及当您忽略它并发出太多重叠发送时重叠I/O(在C++域中)会发生什么...

总而言之,发布多个并发BeginSend调用是获得最佳TCP数据流的方法,但是您需要确保不会像以前那样以无法控制的方式消耗资源时发送"太快",哪个是对于运行代码的机器而言可能是致命的.因此,不要允许无限次BeginSend呼叫,并且理想情况下,应对该框进行分析,以确保您不会耗尽系统范围的资源.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有