【问题标题】:Winsock WSAAsyncSelect sending without an infinite bufferWinsock WSAAsyncSelect 在没有无限缓冲区的情况下发送
【发布时间】:2011-03-02 10:47:03
【问题描述】:

这更像是一个设计问题,而不是一个特定的代码问题,我确定我错过了明显的,我只需要另一双眼睛。

我正在编写一个基于 WSAAsyncSelect 的多客户端服务器,每个连接都构成我编写的连接类的一个对象,其中包含相关的设置和缓冲区等。

我的问题涉及 FD_WRITE,我了解它是如何运作的:在建立连接后立即发送一个 FD_WRITE。此后,您应该发送,直到收到 WSAEWOULDBLOCK 为止,此时您将剩余要发送的内容存储在缓冲区中,并等待被告知可以再次发送。

这就是我有问题的地方,我在每个连接对象中使这个保持缓冲区有多大?直到收到新的 FD_WRITE 的时间量是未知的,在此期间我可能会尝试发送很多东西,一直添加到我的传出缓冲区。如果我使缓冲区动态化,内存使用可能会因任何原因而失控,我无法发送()并减少缓冲区。

所以我的问题是您通常如何处理这种情况?请注意,我不是在谈论 winsock 使用的网络缓冲区本身,而是我自己创建的用于“排队”发送的一个。

希望我解释得足够清楚,谢谢大家!

【问题讨论】:

    标签: c++ winsock send wsaasyncselect


    【解决方案1】:

    当然,正确的设计取决于您的应用程序的性质。

    一些程序可以在必须使用它之前预测可以生成的数据量,因此它们可以使用固定大小的缓冲区。例如,我设计的一个协议有一个命令响应结构和一个 2 字节长度的前缀,所以我可以使用 64K 缓冲区并且知道我永远不会溢出它们。如果缓冲区已满,则程序必须等待回复才能从该缓冲区发送数据,因此不会再向该缓冲区添加数据。

    固定大小缓冲区的另一个好用途是当数据来自另一个 I/O 源时。考虑一个 Web 服务器:在最基本的情况下,它从磁盘中抓取文件并将它们吐出到网络上。因此,您知道一次从磁盘读取多少数据,因此您知道缓冲区必须有多大。

    我无法找到使用动态缓冲区的充分理由。

    您不需要它们的主要原因是TCP's sliding window。如果其中一个连接对等方停止接收数据,则远程对等方的堆栈将在 TCP 窗口填满时停止发送数据。未读数据将保留在接收堆栈的缓冲区中,直到它被发送到请求它的程序。这为接收器提供了一种将传入数据限制到它可以处理的水平的方法。据我所知,这使得固定大小的缓冲区在所有条件下都是实用的。

    【讨论】:

    • 您好,感谢您的回答。我的应用程序设置类似,数据包被定义为大小指令数据,每个最多占用 64k,因此对于接收,我可以轻松定义最大缓冲区大小。这给我留下了另一个我不确定如何回答的问题。它涉及“缓冲区已满”的情况,我该如何处理。如果用户点击了一个按钮,该按钮将向服务器发送数据包,但由于缓冲区已满而无法完成,则我的 UI 未按预期运行。我要等到用户重复命令吗?谢谢!
    • 我会在您知道如何创建每个传出数据包后立即构建它,将其放入链表中,并让您的 FD_WRITE 处理程序使用这些块发送数据。
    • 看,但链表只是托管的动态内存——与我原来的方法并没有什么不同。但是感谢您的帮助,我将更新我的代码以使用链接列表,而不是我现在拥有的自定义解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    相关资源
    最近更新 更多