GetQueuedCompletionStatus-如何在没有任何套接字结构的情况下读取客户端消息

GetQueuedCompletionStatus-如何在没有任何套接字结构的情况下读取客户端消息,c,windows,winsock2,iocp,C,Windows,Winsock2,Iocp,我正在尝试在Windows中使用C学习IOCP。其想法是拥有一个非阻塞服务器,该服务器具有处理客户端消息的线程 我现在知道如何接受客户了,等等 但我仍然不明白如何从GetQueuedCompletionStatus()读取并打印每个客户端的消息 我在网上看到,所有人都通过GetQueuedCompletionStatus()使用LPOVERLAPPED参数传递一个结构来引用它,但是如果没有任何结构,该怎么做呢 有人能告诉我这是否可行,并举一个小例子吗?您必须跟踪传递给WSARecv()等的缓冲区

我正在尝试在Windows中使用C学习IOCP。其想法是拥有一个非阻塞服务器,该服务器具有处理客户端消息的线程

我现在知道如何接受客户了,等等

但我仍然不明白如何从
GetQueuedCompletionStatus()
读取并打印每个客户端的消息

我在网上看到,所有人都通过
GetQueuedCompletionStatus()
使用
LPOVERLAPPED
参数传递一个结构来引用它,但是如果没有任何结构,该怎么做呢


有人能告诉我这是否可行,并举一个小例子吗?

您必须跟踪传递给
WSARecv()
等的缓冲区。您可以通过将重叠的
与每个缓冲区关联来实现这一点。当
GetQueuedCompletionStatus()
告诉您哪个
OVERLAPPED
已完成时,您就知道关联的缓冲区已准备就绪

这通常通过定义一个
OVERLAPPED
作为其第一个成员的
struct
来处理,因此指向
OVERLAPPED
的指针也等于指向
struct
的指针。然后,您可以在
struct
中放入您想要的任何其他详细信息,如缓冲区、套接字等,以及您的应用程序处理数据所需的任何信息

例如:

enum IocpOp{opRead,opWrite};
类型定义结构
{
WSAOVERLAPPED ov;
IocpOp操作码;
插座sckt;
字节缓冲区[256];
德沃德缓冲区;
}MYIOCPINFO,*PMYIOCPINFO;
无效IoComplete(PMYIOCPINFO io,DWORD错误代码,DWORD numBytesTransferred)
{
如果(错误代码!=错误\u成功)
{
//根据需要处理故障。。。
免费(io);
返回;
}
开关(io->操作码)
{
案例阅读:
//根据需要使用io->buffer(缓冲区)至numBytesTransferred。。。
打破
案例opWrite:
如果(numBytesTransferrednumBytesInBuffer)
{
信息->numBytesInBuffer-=numBytesTransferred;
memmove(io->buffer,io->buffer+numBytesTransferred,io->numBytesInBuffer);
WSABUF buf;
buf.len=io->numBytesInBuffer;
buf.buf=(CHAR*)io->buffer;
if(WSASend(io->sckt,&buf,1,NULL,0,&(io->ov),NULL)=SOCKET\u错误)
{
如果(WSAGetLastError()!=WSA\u IO\u挂起)
{
//根据需要处理故障。。。
免费(io);
}
}
返回;
}
打破
}
//在io->sckt上为下一个I/O操作重用io
//或免费io现在如果完成使用它。。。
免费(io);
}
}
...
PMYIOCPINFO io=malloc(sizeof(MYIOCPINFO));
如果(!io)。。。
io->opCode=opRead;
io->sckt=sckt;
WSABUF buf;
buf.len=sizeof(io->buffer);
buf.buf=(CHAR*)io->buffer;
DWORD dwFlags=0;
if(WSARecv(sckt,&buf,1,NULL,&dwFlags,&(io->ov),NULL)=套接字错误)
{
如果(WSAGetLastError()!=WSA\u IO\u挂起)
IoComplete(io,WSAGetLastError(),0);
}
...
PMYIOCPINFO io=malloc(sizeof(MYIOCPINFO));
如果(!io)。。。
io->opCode=opWrite;
io->sckt=sckt;
//根据需要填充io->缓冲区。。。
io->numBytesInBuffer=。。。;
WSABUF buf;
buf.len=io->numBytesInBuffer;
buf.buf=(CHAR*)io->buffer;
if(WSASend(sckt,&buf,1,NULL,0,&(io->ov),NULL)=套接字错误)
{
如果(WSAGetLastError()!=WSA\u IO\u挂起)
IoComplete(io,WSAGetLastError(),0);
}
...
DWORD DWBYTESTTRANSFERRED=0;
ULONG_PTR ulCompletionKey=0;
LPOVERLAPPED LPOVERLAPPED=NULL;
if(GetQueuedCompletionStatus(hIOCP、&DWBYTESTTransfered、&ulCompletionKey、&lpOverlapped、INFINITE))
{
如果在CreateIOCompletionPort()中指定了(ulCompletionKey==MySocketIOCPKey)//则。。。
{
IoComplete((PMYIOCPINFO)lpOverlapped,ERROR\u SUCCESS,dwbytesttransfered);
}
其他的
{
...
}
}
其他的
{
如果(重叠)
{
//属于ulCompletionKey的I/O操作失败。。。
如果在CreateIOCompletionPort()中指定了(ulCompletionKey==MySocketIOCPKey)//则。。。
{
IoComplete((PMYIOCPINFO)lpOverlapped,GetLastError(),dwbytesttransferred);
}
其他的
{
...
}
}
其他的
{
//GetQueuedCompletionStatus()本身失败。。。
}
}

您必须跟踪传递给
WSARecv()
等的缓冲区。您可以通过将重叠的
与每个缓冲区关联来实现这一点。当
GetQueuedCompletionStatus()
告诉您哪个
OVERLAPPED
已完成时,您就知道关联的缓冲区已准备就绪

这通常通过定义一个
OVERLAPPED
作为其第一个成员的
struct
来处理,因此指向
OVERLAPPED
的指针也等于指向
struct
的指针。然后,您可以在
struct
中放入您想要的任何其他详细信息,如缓冲区、套接字等,以及您的应用程序处理数据所需的任何信息

例如:

enum IocpOp{opRead,opWrite};
类型定义结构
{
WSAOVERLAPPED ov;
IocpOp操作码;
插座sckt;
字节缓冲区[256];
德沃德缓冲区;
}MYIOCPINFO,*PMYIOCPINFO;
无效IoComplete(PMYIOCPINFO io,DWORD错误代码,DWORD numBytesTransferred)
{
如果(错误代码!=错误\u成功)
{
//根据需要处理故障。。。
免费(io);
返回;
}
开关(io->操作码)
{
案例阅读:
//根据需要使用io->buffer(缓冲区)至numBytesTransferred。。。
打破
案例opWrite:
如果(numBytesTransferrednumBytesInBuffer)
{
信息->numBytesInBuffer-=numBytesTransferred;
memmove(io->buffer,io->buffer+numBytesTransferred,io->numBytesInBuffer);
WSABUF buf;
buf.len=io->numBytesInBuffer;