gpt4 book ai didi

c++ - 在 MFC 应用程序中未调用重叠的 WSARecv() 回调

转载 作者:太空宇宙 更新时间:2023-11-04 12:22:53 26 4
gpt4 key购买 nike

我有一个 COM 组件,使用 C++ 和 ATL 实现,它使用重叠套接字 I/O。在与服务器建立连接后,它立即在套接字上开始重叠读取,代码如下:

// Pass pointer to this instance as hEvent parameter, for use by callback
m_recvOverlapped.hEvent = reinterpret_cast<HANDLE>(this);

int rc = ::WSARecv(m_s, &wsabuf, 1, &m_recvNumberOfBytes, &m_recvFlags, &m_recvOverlapped, RecvCallback);
if (rc == SOCKET_ERROR)
{
// If error is WSA_IO_PENDING, then the I/O is still in progress. Otherwise, something bad happened.
int error = ::WSAGetLastError();
if (error != WSA_IO_PENDING)
{
ReceiveError(error);
}
}

我有一个看起来像这样的回调函数:

void CALLBACK CMySocket::RecvCallback(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
CMySocket* socket = reinterpret_cast<CMySocket*>(lpOverlapped->hEvent);
ATLASSERT(socket != 0);
if (!socket)
return;

socket->ReceiveCompleted(dwError, cbTransferred, lpOverlapped, dwFlags);
}

此 COM 组件在单元测试中、在命令行应用程序中使用时以及在 .NET GUI 应用程序中使用时(通过 COM 互操作)都可以正常工作。但是,当我在 MFC 应用程序中使用此组件时,服务器向其发送数据时,RecvCallback 永远不会被调用。

WSARecv() 返回 SOCKET_ERRORWSAGetLastError() 返回 WSA_IO_PENDING,正如预期的异步重叠读取.

当我使用 SysInternals TcpView 应用程序查看发生的情况时,它表明客户端正在接收数据。但是永远不会调用回调。

通过连接的套接字向服务器发送数据工作正常。

我正在我的 MFC 应用程序的 InitInstance() 方法中调用 CoInitializeEx()WSAStartup()

有什么想法吗?

最佳答案

是的,确实如此。仅当线程进入“可警告”等待状态时才处理 APC - 调用 SleepExWaitForMultipleObjectsExMsgWaitForMultipleObjectsEx 函数。

我想纠正你的一点是,使用 OVERLAPPEDhEvent 成员作为“用户”数据的占位符不是一个好主意。因为当您的 I/O 完成时,操作系统将尝试设置此“事件”。

将一些“用户”信息传递到回调路由的常见方法实际上是使用自定义结构来取代 OVERLAPPED,根据需要添加更多成员(又名 OVERLAPPED_PLUS)。然后你的回调路由可能会将 OVERLAPPED 转换到你的 OVERLAPPED_PLUS,在那里你会看到所有成员。

另一点:由于您正在编写 COM 对象 - 您可能没有能力编写自己的消息循环,因此可能难以保证进入可警告等待。

关于c++ - 在 MFC 应用程序中未调用重叠的 WSARecv() 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4015220/

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