这是我的PER_IO_CONTEXT结构(我把它们存储在单独的链表中):
typedef struct _PER_IO_CONTEXT { SLIST_ENTRY ItemEntry; WSAOVERLAPPED Overlapped; WSABUF wsabuf; /* some other data*/ } PER_IO_CONTEXT, *PPER_IO_CONTEXT;
下面是WSAsend,使用列表获取WSAOVERLAPPED结构:
... PSLIST_HEADER pListHead; ... PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(pListHead); PPER_IO_CONTEXT ovl = (PPER_IO_CONTEXT)pListEntry; WSASend(pTmp1->Socket,..., &(ovl->Overlapped), NULL);
和GQCS获得通知的最后一部分:
LPWSAOVERLAPPED lpOverlapped = NULL; PPER_IO_CONTEXT lpIOContext = NULL; .... GetQueuedCompletionStatus(..... (LPOVERLAPPED *)&lpOverlapped, INFINITE); lpIOContext = (PPER_IO_CONTEXT)lpOverlapped; lpIOContext->wsabuf // this fail
正如你可以看到下面的转换lpIOContext =(PPER_IO_CONTEXT)lpOverlapped不起作用,因为WSAsend提供了wsaoverlapped – PER_IO_CONTEXT结构的第二个成员,所以在这种情况下,不能使用像lpIOContext->的引用。
有办法处理这种情况?
要获得相应的PER_IO_CONTEXT结构的地址,你可以使用这个:
lpIOContext = CONTAINING_RECORD(lpOverlapped, PER_IO_CONTEXT, Overlapped);
CONTAINING_RECORD是一个在VC\crt\src\collections.h
中定义的宏,方法如下:
#define CONTAINING_RECORD(address, type, field) \ ((type *)((char *)(address) - (ULONG_PTR)(&((type *)0)->field)))
更多信息: http : //msdn.microsoft.com/en-us/library/windows/hardware/ff542043%28v=vs.85%29.aspx
我不确定是否有支持的机制将指针转换为结构的成员指向结构的指针。 你可以把所有的东西都转换成BYTE *
然后做一些算术运算,但是根据你的需要,重新整理可能会更清洁,以避免这种必要性:
typedef struct _PER_IO_CONTEXT { WSAOVERLAPPED Overlapped; WSABUF wsabuf; /* some other data*/ } PER_IO_CONTEXT, *PPER_IO_CONTEXT; typedef struct _PER_IO_CONTEXT_LIST_ITEM { SLIST_ENTRY ItemEntry; PER_IO_CONTEXT Item; } PER_IO_CONTEXT_LIST_ITEM, *PPER_IO_CONTEXT_LIST_ITEM;