1

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

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

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

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

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

希望我解释得很好,谢谢大家!

4

1 回答 1

0

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

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

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

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

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

于 2010-06-14T14:41:16.713 回答