オーバーラップ ソケット I/O を使用する、ATL を使用して C++ で実装された COM コンポーネントがあります。サーバーへの接続が確立された直後に、次のようなコードを使用して、ソケットでオーバーラップ読み取りを開始します。
// 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()
非同期オーバーラップ読み取りで予想されるように、return SOCKET_ERROR
、およびreturns 。WSAGetLastError()
WSA_IO_PENDING
SysInternals TcpView アプリを使用して何が起こっているかを監視すると、クライアントがデータを受信していることがわかります。しかし、コールバックが呼び出されることはありません。
接続されたソケットを介してサーバーにデータを送信すると、正常に機能します。
MFC アプリのメソッドでCoInitializeEx()
andを呼び出しています。WSAStartup()
InitInstance()
何か案は?