gpt4 book ai didi

c++ - 如何使用 IOCP 将用户定义的数据传递给工作线程?

转载 作者:搜寻专家 更新时间:2023-10-31 00:21:38 24 4
gpt4 key购买 nike

嘿...我使用 I/O 完成端口和 winsock 创建了一个小型测试服务器。我可以成功连接套接字句柄并将其与完成端口相关联。但我不知道如何将用户定义的数据结构传递到 wroker 线程中......

到目前为止,我尝试将用户结构作为(ULONG_PTR)&structure 作为 CreateIoCompletionPort() 关联调用中的 Completion Key 传递但这没有用。

现在我尝试定义自己的 OVERLAPPED 结构并使用 CONTAINING_RECORD(),如此处所述 http://msdn.microsoft.com/en-us/magazine/cc302334.aspxhttp://msdn.microsoft.com/en-us/magazine/bb985148.aspx . 但这也行不通。 (我得到了 pHelper 内容的异常值)

所以我的问题是:如何使用 WSARecv()、GetQueuedCompletionStatus() 和完成数据包或 OVERLAPPED 结构将数据传递给工作线程?

编辑:我怎样才能成功传输“每个连接数据”?...似乎我做错了(如上面两个链接中所解释的)。

这是我的代码:(是的,它很丑,而且是唯一的测试代码)

struct helper
{
SOCKET m_sock;
unsigned int m_key;
OVERLAPPED over;
};


///////

SOCKET newSock = INVALID_SOCKET;
WSABUF wsabuffer;
char cbuf[250];
wsabuffer.buf = cbuf;
wsabuffer.len = 250;
DWORD flags, bytesrecvd;


while(true)
{
newSock = accept(AcceptorSock, NULL, NULL);
if(newSock == INVALID_SOCKET)
ErrorAbort("could not accept a connection");

//associate socket with the CP
if(CreateIoCompletionPort((HANDLE)newSock, hCompletionPort, 3,0) != hCompletionPort)
ErrorAbort("Wrong port associated with the connection");
else
cout << "New Connection made and associated\n";

helper* pHelper = new helper;
pHelper->m_key = 3;
pHelper->m_sock = newSock;
memset(&(pHelper->over), 0, sizeof(OVERLAPPED));
flags = 0;
bytesrecvd = 0;

if(WSARecv(newSock, &wsabuffer, 1, NULL, &flags, (OVERLAPPED*)pHelper, NULL) != 0)
{
if(WSAGetLastError() != WSA_IO_PENDING)
ErrorAbort("WSARecv didnt work");
}
}

//Cleanup
CloseHandle(hCompletionPort);
cin.get();
return 0;
}

DWORD WINAPI ThreadProc(HANDLE h)
{
DWORD dwNumberOfBytes = 0;
OVERLAPPED* pOver = nullptr;
helper* pHelper = nullptr;
WSABUF RecvBuf;
char cBuffer[250];
RecvBuf.buf = cBuffer;
RecvBuf.len = 250;
DWORD dwRecvBytes = 0;
DWORD dwFlags = 0;
ULONG_PTR Key = 0;

GetQueuedCompletionStatus(h, &dwNumberOfBytes, &Key, &pOver, INFINITE);

//Extract helper
pHelper = (helper*)CONTAINING_RECORD(pOver, helper, over);


cout << "Received Overlapped item" << endl;
if(WSARecv(pHelper->m_sock, &RecvBuf, 1, &dwRecvBytes, &dwFlags, pOver, NULL) != 0)
cout << "Could not receive data\n";
else
cout << "Data Received: " << RecvBuf.buf << endl;

ExitThread(0);
}

最佳答案

如果你像这样传递你的结构,它应该可以正常工作:

helper* pHelper = new helper;
CreateIoCompletionPort((HANDLE)newSock, hCompletionPort, (ULONG_PTR)pHelper,0);
...


helper* pHelper=NULL;
GetQueuedCompletionStatus(h, &dwNumberOfBytes, (PULONG_PTR)&pHelper, &pOver, INFINITE);

编辑以添加每个 IO 数据:

异步 ​​api 经常被滥用的功能之一是它们不复制 OVERLAPPED 结构,它们只是使用提供的结构 - 因此从 GetQueuedCompletionStatus 返回的重叠结构指向最初提供的结构。所以:

struct helper {
OVERLAPPED m_over;
SOCKET m_socket;
UINT m_key;
};

if(WSARecv(newSock, &wsabuffer, 1, NULL, &flags, &pHelper->m_over, NULL) != 0)

再次注意,在您的原始示例中,您的转换有误。 (OVERLAPPED*)pHelper 将指针传递给辅助结构的 START,但 OVERLAPPED 部分是最后声明的。我将其更改为传递实际重叠部分的地址,这意味着代码无需强制转换即可编译,这让我们知道我们正在做正确的事情。我还将重叠的结构移动到该结构的第一个成员。

获取另一端的数据:

OVERLAPPED* pOver;
ULONG_PTR key;
if(GetQueuedCompletionStatus(h,&dw,&key,&pOver,INFINITE))
{
// c cast
helper* pConnData = (helper*)pOver;

在这一点上,overlapped 结构是辅助结构的第一个成员尤为重要,因为这使得从 api 给我们的 OVERLAPPED* 和我们真正想要的 helper* 中转换回来变得容易。

关于c++ - 如何使用 IOCP 将用户定义的数据传递给工作线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4344162/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com