1

我的问题:我的 Completionport 服务器将从不同的客户端接收未知大小的数据,问题是,我不知道如何避免缓冲区溢出/如何避免我的(接收)缓冲区被数据“过度填充”。

现在到问题:1)如果我通过 WSARecv 进行接收呼叫,工作线程是否像回调函数一样工作?我的意思是,它是仅在完成后才挖掘接收呼叫,还是在接收发生时也挖掘它?lpNumberOfBytes(来自 GetQueuedCompletionStatus)变量是否包含到目前为止接收到的字节数或接收到的总字节数?

2)如何避免溢出,我想到了动态分配的缓冲区结构,但话又说回来,我如何找出包会有多大?

编辑:我不想问这个,但是有没有“简单”的方法来管理缓冲区并避免溢出?同步听起来对我来说是无限的,至少现在

4

2 回答 2

1

如果我通过 WSARecv 进行接收呼叫,工作线程是否像回调函数一样工作?

请参阅@valdo 帖子。完成数据 si 排队到您的线程池中,并且准备好处理它。

“我的意思是,它只有在完成后才挖掘接收呼叫吗?” 是的——因此得名。请注意,“完成”的含义可能会有所不同。取决于协议。使用 TCP,这意味着已从对等方接收到一些流数据字节。

'lpNumberOfBytes(来自 GetQueuedCompletionStatus)变量是否包含到目前为止接收到的字节数或接收到的总字节数?它包含接收并加载到仅在该 IOCP 完成中提供的缓冲区数组中的字节数。

“如何避免溢出,我想到了动态分配的缓冲区结构,但话又说回来,我如何找出包将得到多大?” 如果您提供缓冲区数组,则不会出现溢出 - 加载缓冲区的内核线程不会超过传递的缓冲区长度。在应用程序级别,鉴于 TCP 的流式传输特性,由您决定如何将缓冲区数组处理为可用的应用程序级别协议单元。您必须利用您对所提供服务的了解来决定合适的缓冲区管理方案。

最后一个 IOCP 服务器有点通用。我使用了一个缓冲池数组和一个在启动时分配的“缓冲载体”对象池(以及一个套接字对象池)。每个缓冲池保存不同大小的缓冲区。在建立新连接时,我使用最小池中的一个缓冲区发出了 WSARecv。如果这个缓冲区被完全填满,我将下一个最大池中的一个缓冲区用于下一个 WSARecv,依此类推。

然后是防止使用多个处理程序线程进行无序缓冲所需的序列号问题:(

于 2012-02-17T15:28:27.857 回答
1

_1。完成端口是一种队列(具有复杂的逻辑,涉及等待从队列中取出 I/O 完成的线程的优先级)。每当 I/O 完成(无论成功与否),它都会排队进入完成端口。然后它被一个名为GetQueuedCompletionStatus.

这样您就永远不会将“进行中”的 I/O 出列。此外,它由您的工作线程异步处理。也就是说,它会延迟到您的线程调用GetQueuedCompletionStatus.

_2。这实际上是一个复杂的问题。总体而言,同步并不是一项微不足道的任务,尤其是在涉及对称多线程时(您有多个线程,每个线程可能都在做所有事情)。

完成 I/O 时收到的参数之一是指向OVERLAPPED结构的指针(您提供给发出 I/O 的函数,例如WSARecv)。分配您自己的基于OVERLAPPED(继承它或将其作为第一个成员)的结构是一种常见的做法。收到完成后,您可以将 dequeuedOVERLAPPED转换为您的实际数据结构。在那里,您可能拥有同步所需的一切:同步对象、状态描述等。

但是请注意,即使您拥有自定义上下文,正确同步事物(以获得良好的性能并避免死锁)也不是一件容易的事。这需要精确的设计。

于 2012-02-17T15:04:31.050 回答