【发布时间】:2015-01-02 13:00:25
【问题描述】:
我一直在研究 TCP/IP IOCP 服务器应用程序。
我一直在测试性能(这似乎与 TCP 吞吐量测试实用程序一致),现在一直在测试数据完整性——这就是我感到“奇怪”的地方。
作为初始测试,我决定让一个测试客户端一遍又一遍地发送一个 1MB 的数据块,该块只是一个一个接一个地递增的整数序列。这个想法是我可以验证每个接收到的数据缓冲区是否与该缓冲区中没有丢失的数据一致,独立于接收到的任何其他缓冲区,这意味着我不需要担心什么顺序线程处理完成的接收。 (为了验证,我提取缓冲区中的第一个整数并向前扫描,如果遇到客户端发送的最大值,则将预期值重置为 0。我还检查以确保每个接收到的数据是 4 的倍数(因为它们是 4 字节整数))。
我似乎偶尔会从缓冲区中丢失随机数据块,这些值会 1 比 1 增加,然后会跳过一堆。代码虽然看起来很简单,而且不多。我最初在 Delphi 中编写了测试,但在遇到这些问题后,我在 Visual Studio 2010 C++ 中重写了一个版本,并且似乎遇到了同样的问题(或至少非常相似)。
在实际系统中显然有更多代码,但我可以在工作线程中将其归结为几乎这样,它只处理完成的接收,验证缓冲区中的数据,然后再次发布它们。在我最初接受连接后,我创建了两个重叠的结构并为每个结构分配 1MB 缓冲区,然后为每个结构调用 WSARecv。我已经仔细检查过,我不会不小心在两者之间共享相同的缓冲区。然后,以下几乎就是重用这些的内容:
DWORD numberOfBytesTransferred = 0;
ULONG_PTR completionKey = NULL;
PMyOverlapped overlapped = nullptr;
while (true)
{
auto queueResult = GetQueuedCompletionStatus(iocp, &numberOfBytesTransferred, &completionKey, (LPOVERLAPPED *)&overlapped, INFINITE);
if (queueResult)
{
switch (overlapped->operation)
{
case tsoRecv:
{
verifyReceivedData(overlapped, numberOfBytesTransferred); // Checks the data is a sequence of incremented integers 1 after the other with no gabs
overlapped->overlapped = OVERLAPPED(); // Reset the OVERLAPPED structure to defaults
DWORD flags = 0;
numberOfBytesTransferred = 0;
auto returnCode = WSARecv(socket, &(overlapped->buffer), 1, &numberOfBytesTransferred, &flags, (LPWSAOVERLAPPED) overlapped, nullptr);
break;
}
default:;
}
}
}
也许我在上面的简单测试中没有处理某种错误或附加信息?我最初有一个 IOCP 客户端发送数据,但在 Delphi 中使用 Indy 阻塞套接字编写了另一个非常简单的客户端。连接后基本上就是一行代码。
while true do
begin
IdTCPClient.IOHandler.WriteDirect(TIdBytes(BigData), Length(BigData));
end;
我还使用不同的异步套接字组件编写了另一台服务器,但至少现在还没有像上面的 IOCP 示例那样检测到接收数据的问题。我可以发布更多代码,可能还有一个要编译的版本,但我想我会发布上面的内容,以防我错过了一些明显的东西。我认为每个套接字使用一个接收和一个发送可以,但我的理解是发布多个以提高性能是有效的。
【问题讨论】:
-
Hmmm... '我还要检查以确保每个缓冲区中接收到的数据是 4 的倍数(因为它们是 4 字节整数'。如何保证每个缓冲区包含精确的TCP 流中 4 个字节的倍数?我建议您检查一下。
-
你是对的,这根本不能保证,这就是为什么我检查以确保 numberOfBytesTransferred 是 4 的倍数并在检测到它时中止测试。然而,碰巧我一直交付的缓冲区是 4 的倍数(我假设是因为我在本地进行测试并且客户端正在发送连续的整齐数据块)。触发检查的唯一时间是当我在调试器中的断线处停止然后恢复时,有时下一个缓冲区是奇数。在这种情况下也很清楚,因为整数远远超出了有效范围。
标签: c++ sockets tcp corrupt iocp