有个Windows网络编程重叠I/O模型的有关问题

有个Windows网络编程重叠I/O模型的问题
先贴代码。

//照书上写的结构体。
typedef struct tagPER_IO_OPERATION_DATA
{
WSAOVERLAPPED overlap ; //重叠结构
WSABUF buffer ; //缓冲区对象
char message[512] ; //缓冲区缓存
DWORD numberOfBytesRecved ; //接收字符数
DWORD flags ; //标志位
SOCKET client ; //套接字
}
PER_IO_OPERATION_DATA, *PPER_IO_OPERATION_DATA ;

//I/O操作完成后,供系统调用的函数
void CALLBACK completionRoutine (DWORD error, DWORD transferred,
LPWSAOVERLAPPED pOverlapped,
DWORD flags)
{
//保存I/O操作的数据
PPER_IO_OPERATION_DATA pPerIOData = (PPER_IO_OPERATION_DATA) pOverlapped ;

if (error != 0 || transferred == 0)
{
cout << "客户端连接断开" << endl ;
//如果发生错误或者没有数据传输,则关闭套接字
closesocket (pPerIOData->client) ;
HeapFree (GetProcessHeap (), 0, pPerIOData) ;
}
else
{
cout << "接收数据长度:" << transferred << endl ;
cout << "数据:" << pPerIOData->buffer.buf << endl ;

pPerIOData->message[transferred] = '\0' ;
ZeroMemory (&pPerIOData->overlap, sizeof (WSAOVERLAPPED)) ;
pPerIOData->buffer.len = 512 ;
pPerIOData->buffer.buf = pPerIOData->message ;

WSARecv (pPerIOData->client, &pPerIOData->buffer, 1,
&pPerIOData->numberOfBytesRecved,
&pPerIOData->flags, &pPerIOData->overlap, completionRoutine) ;
}
}

int main ()
{
//...
//前面是套接字的初始化
wsaEvent = WSACreateEvent () ;
ZeroMemory (&acceptOverlapped, sizeof (WSAOVERLAPPED)) ;
acceptOverlapped.hEvent = wsaEvent ;
dataBuf.len = 512 ;
dataBuf.buf = buffer ; //buffer的定义,char buffer[512] = "" ;

sockaddr_in addrClient ;
int addrClientLen = sizeof (sockaddr_in) ;
SOCKET clientSocket ;

while (true)
{
clientSocket = accept (serverSocket,
(sockaddr *) &addrClient,
&addrClientLen) ; //1处
if (clientSocket == INVALID_SOCKET)
{
cout << "接收错误" << endl ;
closesocket (serverSocket) ;
WSACleanup () ;
return 5 ;
}

cout << "接收到的新连接:" << inet_ntoa (addrClient.sin_addr) << endl ;

//采用例程方法
//可以同时接受几个客户端连接
PPER_IO_OPERATION_DATA pPerIOData = NULL ;
//分配空间
pPerIOData = 
(PPER_IO_OPERATION_DATA) HeapAlloc (GetProcessHeap (), 
HEAP_ZERO_MEMORY, 
sizeof (PER_IO_OPERATION_DATA)) ;
//初始化
pPerIOData->buffer.len = 512 ;
pPerIOData->buffer.buf = pPerIOData->message ;
pPerIOData->client = clientSocket ;
ZeroMemory (pPerIOData->buffer.buf, 512) ;
ZeroMemory (&pPerIOData->overlap, sizeof (WSAOVERLAPPED)) ;

if (WSARecv (pPerIOData->client, &pPerIOData->buffer, 1,
&pPerIOData->numberOfBytesRecved,
&pPerIOData->flags, &pPerIOData->overlap,
completionRoutine) == SOCKET_ERROR)
{
if (WSAGetLastError () != WSA_IO_PENDING)
cout << "接收出现错误" << WSAGetLastError () << endl ;
}

//2处
// HANDLE cEvent ;
// cEvent = CreateEvent (NULL, FALSE, FALSE, NULL) ;
// WaitForSingleObject (cEvent, INFINITE) ;

//3处
//  while (true)
//  {
//  ;
//  }
}

return 0 ;
}
        程序运行后,将套接字初始化完毕,绑定地址和端口,然后监听,进入while循环后在1处(第三段程序19行)阻塞。打开一个客户端程序,连接后,服务端程序往后执行,执行完一遍后,重新在1处阻塞。此时在客户端发送字符数据,服务端可以进入completionRoutine接收并输出到控制台。但如果将2处下面3行取消注释或者3处下面4行取消注释,则服务端不能进入completionRoutine。
        所以请教一下各位,在1处,2处或3处阻塞,服务端程序都不能往后执行,但为什么1处阻塞时可以接收到消息,2或3处则不行?
------解决思路----------------------
参考
Microsoft SDK\samples\netds\GQos\QosEvent\Sender.Cpp
Microsoft SDK\samples\netds\GQos\Qualitative\Receiver.Cpp
Microsoft SDK\samples\netds\GQos\Qualitative\Sender.Cpp
Microsoft SDK\samples\netds\WinSock\ATMEvent\Sender.Cpp
Microsoft SDK\samples\netds\WinSock\iocp\IocpServer.Cpp
Microsoft SDK\samples\netds\WinSock\LSP\spi.cpp
------解决思路----------------------
明白了你的意思,个人觉得,2 3处是整个程序阻塞,包括I/O,所以completionRoutine都无法执行,而accept的阻塞是相对的,不影响IO操作。一般把wsarecv放在单独线程里的用法比较多,也就没有这些问题