0

IO完了ポートを使用するマルチスレッドクライアントを作成しています。

WSA_FLAG_OVERLAPPED属性が設定されているソケットを作成して接続します。

if ((m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
    throw std::exception("Failed to create socket.");
}

if (WSAConnectByName(m_socket, L"server.com", L"80", &localAddressLength, reinterpret_cast<sockaddr*>(&localAddress), &remoteAddressLength, &remoteAddress, NULL, NULL) == FALSE)
{
    throw std::exception("Failed to connect.");
}

IO完了ポートをソケットに関連付けます。

if ((m_hIOCP = CreateIoCompletionPort(reinterpret_cast<HANDLE>(m_socket), m_hIOCP, NULL, 8)) == NULL)
{
    throw std::exception("Failed to create IOCP object.");
}

ソケットを介してデータを送信しようとするまで、すべてうまくいくように見えます。

SocketData* socketData = new SocketData;
socketData->hEvent = 0;

DWORD bytesSent = 0;
if (WSASend(m_socket, socketData->SetBuffer(socketData->GenerateLoginRequestHeader()), 1, &bytesSent, NULL, reinterpret_cast<OVERLAPPED*>(socketData), NULL) == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
    throw std::exception("Failed to send data.");
}

最後のエラーがWSA_IO_PENDINGに設定されたSOCKET_ERRORを返す代わりに、WSASendはすぐに戻ります。

保留するIOが必要であり、その完了をワーカースレッドでもあるスレッド関数で処理する必要があります。

unsigned int __stdcall MyClass::WorkerThread(void* lpThis)
{

}

私は以前にこれを行ったことがありますが、この場合に何が問題になっているのかわかりません。この問題の解決にご協力いただければ幸いです。

4

2 に答える 2

2

あなたがそうしなければ、それは問題ではありません。

SetFileCompletionNotificationModes()を呼び出しておらず、成功時に完了ポート処理をスキップするフラグを設定している限り、WSARecv(またはその他)がSUCCESSを返しても、ERROR_IO_PENDINGが返された場合と同じようにIO完了パケットがIOCPにキューに入れられます。したがって、エラーが返されない場合に特別な処理を行う必要はありません。

詳細については、 http://support.microsoft.com/default.aspx?scid = kb;en-us;Q192800を参照してください。

于 2010-06-13T10:56:17.033 に答える
1

まず、呼び出しをより明確なロジックに分割します。

int nRet = WSASend(m_socket, socketData->SetBuffer(socketData->GenerateLoginRequestHeader()), 1, NULL, NULL, reinterpret_cast<OVERLAPPED*>(socketData), NULL);
if (nRet == SOCKET_ERROR)
{
    if ((WSAGetLastError()) == WSA_IO_PENDING)
        nRet = 0; // ok
    else
        throw std::exception("Failed to send data."); // failed
}

また、私のコードでわかるように、WSASendに従って「&bytesSent」パラメーターを渡さないでください。

lpOverlappedパラメーターがNULLでない場合は、誤った結果を回避するために、このパラメーターにNULLを使用してください。

それに加えて、WSASend()の呼び出しは問題ないように見えます。

于 2010-06-13T21:11:15.957 に答える