我正在使用IOCP编写多播生产者和多播消费者应用程序。我的制作人应用程序是多线程的,并发布到多个多播渠道。每个通道都在自己的线程上发布,所以我确定发送缓冲区没有同步/竞争条件问题。事实上,使用wire shark,数据报看起来很好(偶尔会出现一个格式错误(不确定UDP数据报是否正常)。)
我的消费者应用程序是我遇到麻烦的地方。我的消费者应用程序也是多线程的。但同样,对于任何单个多播通道只调用一个WSARecv(每个通道都有自己的一组缓冲区),因此只有一个线程访问缓冲区。当我调用GetQueuedCompletionStatus时,我处理数据,然后调用WSARecv再次启动进程。
我看到的问题是GetQueuedCompletionStatus返回缓冲区中的旧数据(我重用了缓冲区)。当我将缓冲区写入日志文件时,我可以看到数据没有变化,尽管我的Wire Shark记录显示数据报很好。这个错误的间歇性似乎指向同步问题,但我仔细查看了库,我没有看到使用TCP的这个问题。 GetQueuedCompletionStatus有没有办法返回虚假数据?
bool cont = true;
DWORD xferd;
OVERLAPPED* overlapped = NULL;
TTOverlapped<InternalEndpointPtr>* tto;
ULONG_PTR key;
while (cont) {
BOOL b = GetQueuedCompletionStatus(iocp_, &xferd, &key, &overlapped, INFINITE);
// only a single WSARecv called per overlapped structure
// it's assumed that if overlapped != NULL, WSARecv call has completed
if (overlapped) {
tto = static_cast<TTOverlapped<InternalEndpointPtr>*>(overlapped);
switch (tto->opCode()) {
case IOCP_OP_CODE_READ: readMessage(tto, xferd); break;
case IOCP_OP_CODE_WRITE:
if (xferd == 0)
std::printf("Send operation failed: %d.\n", WSAGetLastError());
break;
case IOCP_OP_CODE_NEW_CLIENT:
tto->endpoint()->recv();
delete tto;
break;
case IOCP_OP_CODE_SHUTDOWN:
cont = false;
break;
default
std::printf("Not expecting this: %d!!!\n", tto->opCode());
break;
}
}
else {
DWORD d = GetLastError();
if (d != 995)
Logger::log(LOG_LEVEL_STATUS, LOG_TYPE_SYSTEM, "InternalIpcProcessor::processIocpCallbacks(): GetQueuedCompletionStatus returned FALSE. Thread id = %d. GetLastError = %d.", ::GetCurrentThreadId(), GetLastError());
}
}