У меня есть COM-компонент, реализованный на C ++ с ATL, который использует перекрывающийся сокет ввода-вывода. Сразу после установления соединения с сервером он запускает перекрывающееся чтение в сокете с кодом, подобным следующему:
// 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_ERROR
, а WSAGetLastError()
возвращает WSA_IO_PENDING
, как и ожидалось для асинхронных перекрывающихся операций чтения.
Когда я использую приложение SysInternals TcpView для наблюдения за происходящим, это указывает на то, что клиент получает данные. Но обратный вызов никогда не вызывается.
Отправка данных на сервер через подключенный сокет работает нормально.
Я звоню CoInitializeEx()
и WSAStartup()
в методе InitInstance()
моего приложения MFC.
Есть идеи?