在windows网络编程中,关于完成端口部分中:
定义结构:
typedef struct{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char Buffer[DATABUF_SIZE];
int OperationType;
// other useful information
}PER_IO_DATA;在listen线程中:
当有client连接上来后进行I/O投递,
在WSARecv之前执行:
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATABUF_SIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
PerIoData->OperationType = RECV_POSTED;
Flags = 0;
WSARecv(acceptSocket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,&(PerIoData->Overlapped), NULL);在工作线程中:
GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&Overlapped,INFINITE);PerIoData = CONTAINING_RECORD((LPOVERLAPPED *)&Overlapped,PER_IO_DATA,Overlapped);
很奇怪的是,此时PerIoData中OperationType没有数据了,我认为应该是RECV_POSTED啊!
定义结构:
typedef struct{
OVERLAPPED Overlapped;
WSABUF DataBuf;
char Buffer[DATABUF_SIZE];
int OperationType;
// other useful information
}PER_IO_DATA;在listen线程中:
当有client连接上来后进行I/O投递,
在WSARecv之前执行:
ZeroMemory(&(PerIoData->Overlapped), sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DATABUF_SIZE;
PerIoData->DataBuf.buf = PerIoData->Buffer;
PerIoData->OperationType = RECV_POSTED;
Flags = 0;
WSARecv(acceptSocket, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,&(PerIoData->Overlapped), NULL);在工作线程中:
GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&Overlapped,INFINITE);PerIoData = CONTAINING_RECORD((LPOVERLAPPED *)&Overlapped,PER_IO_DATA,Overlapped);
很奇怪的是,此时PerIoData中OperationType没有数据了,我认为应该是RECV_POSTED啊!
可是我看windows网络编程上就是这样的啊!
ASSERT(pThis); HANDLE hCompletionPort = pThis->m_hCompletionPort;
DWORD dwIoSize;
LPOVERLAPPED lpOverlapped;
OVERLAPPEDPLUS * lpOverlappedPlugs;
ClientContext* lpClientContext;
BOOL bErro; while(1)
{
bErro = FALSE;
lpClientContext = NULL;
lpOverlapped = NULL;
lpOverlappedPlugs = NULL;
TRACE2("while : %s-%d ThreadPoolFunc\n",__FILE__,__LINE__);
// Get a completed IO request.
BOOL bIORet = GetQueuedCompletionStatus(
hCompletionPort,
&dwIoSize,
(LPDWORD) &lpClientContext,
&lpOverlapped, INFINITE);
DWORD dwIOError = GetLastError();
if (!bIORet && dwIOError != WAIT_TIMEOUT )//
{
if (lpClientContext)
pThis->RemoveStaleClient(lpClientContext, FALSE);
continue;
bErro = TRUE;
}
lpOverlappedPlugs = (OVERLAPPEDPLUS *)lpOverlapped;
int ret = 0;
if(!bErro)
{
if(bIORet && NULL != lpOverlapped && NULL != lpClientContext)
{
if(lpOverlappedPlugs->m_ioType == IORead)
{
if(dwIoSize == 0)
{
if (lpClientContext)
pThis->RemoveStaleClient(lpClientContext, FALSE);
continue;
}
lpClientContext->m_translate = dwIoSize;
ret = lpClientContext->DelWithResData();
}else
if(lpOverlappedPlugs->m_ioType == IOInitialize)
{
ret = 1;
}else
{
ret = 0;
}
}
}
//delete plug pre call
if(bIORet && NULL == lpOverlapped && NULL == lpClientContext)
{
break;
}
OVERLAPPEDPLUS * lpPrePlugs = NULL;
if(! bErro && ret )
{
// issue a read request
lpPrePlugs = lpClientContext->m_preCall;
OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IORead);
ULONG ulFlags = MSG_PARTIAL;
lpClientContext->m_preCall = pOverlap;
UINT nRetVal = WSARecv(lpClientContext->m_Socket,
&lpClientContext->m_wsaInBuffer,
1,
&dwIoSize,
&ulFlags,
&pOverlap->m_ol,
NULL);
if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
pThis->RemoveStaleClient( lpClientContext, FALSE );
}
}
if(lpOverlappedPlugs && ret)
{
if(lpPrePlugs == lpOverlappedPlugs)
{
if(lpPrePlugs->m_ioType == IOInitialize ||
lpPrePlugs->m_ioType == IORead)
delete lpPrePlugs; // from previous call
}
}
}
否则可能在工作线程中该内存有可能失效
从而得到不正确的值
GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&Overlapped,INFINITE);
这句中,应该为:(LPOVERLAPPED *)&PerIoData不过现在又有一个新问题了,在结构PER_IO_DATA中,为什么每次使用前都不用对Buffer清零啊?