非同期ソケットがあり、connect()+ GetLastError()を呼び出して、期待どおりにWSA_WOULD_BLOCKを返します。そこで、スレッドの「受信/読み取り」を開始し、イベントをFD_READおよびFD_CLOSEにサブスクライブします。
ストーリーは次のとおりです。サーバーが稼働していないため、接続は順次失敗します。受信スレッドはすぐにFD_CLOSEを取得するはずであり、クリーニングをフォローアップする必要があることを理解しています。
それは起こりません。FD_CLOSEはどれくらい早く受け取る必要がありますか?それは適切なアプローチですか?connect()が失敗したことを理解する他の方法はありますか?ソケットが接続されていない場合、FD_CLOSEを受け取ることがありますか?
DoConnect()の呼び出しが成功した後、受信スレッドとサブスクライブイベントを開始しますが、競合状態のためにFD_CLOSEを取得できないのではないかと心配しています。
ここにいくつかのコードがあります:
int RecvSocketThread::WaitForData()
{
int retVal = 0
while (!retVal)
{
// sockets to pool can be added on other threads.
// please validate that all of them in the pool are connected
// before doing any reading on them
retVal = DoWaitForData();
}
}
int RecvSocketThread::DoWaitForData()
{
// before waiting for incoming data, check if all sockets are connected
WaitForPendingConnection_DoForAllSocketsInThePool();
// other routine to read (FD_READ) or react to FD_CLOSE
// create array of event (each per socket) and wait
}
void RecvSocketThread::WaitForPendingConnection_DoForAllSocketsInThePool()
{
// create array and set it for events associated with pending connect sockets
HANDLE* EventArray = NULL;
int counter = 0;
EventArray = new HANDLE[m_RecvSocketInfoPool.size()];
// add those event whose associated socket is still not connected
// and wait for FD_WRITE and FD_CLOSE. At the end of this function
// don't forget to switch them to FD_READ and FD_CLOSE
while (it != m_RecvSocketInfoPool.end())
{
RecvSocketInfo* recvSocketInfo = it->second;
if (!IsEventSet(recvSocketInfo->m_Connected, &retVal2))
{
::WSAEventSelect(recvSocketInfo->m_WorkerSocket, recvSocketInfo->m_Event, FD_WRITE | FD_CLOSE);
EventArray[counter++] = recvSocketInfo->m_Event;
}
++it;
}
if (counter)
{
DWORD indexSignaled = WaitForMultipleObjects(counter, EventArray, WaitAtLeastOneEvent, INFINITE);
// no matter what is further Wait doen't return for failed to connect socket
if (WAIT_OBJECT_0 <= indexSignaled &&
indexSignaled < (WAIT_OBJECT_0 + counter))
{
it = m_RecvSocketInfoPool.begin();
while (it != m_RecvSocketInfoPool.end())
{
RecvSocketInfo* recvSocketInfo = it->second;
if (IsEventSet(recvSocketInfo->m_Event, NULL))
{
rc = WSAEnumNetworkEvents(recvSocketInfo->m_WorkerSocket,
recvSocketInfo->m_Event, &networkEvents);
// Check recvSocketInfo->m_Event using WSAEnumnetworkevents
// for FD_CLOSE using FD_CLOSE_BIT
if ((networkEvents.lNetworkEvents & FD_CLOSE))
{
recvSocketInfo->m_FD_CLOSE_Recieved = 1;
*retVal = networkEvents.iErrorCode[FD_CLOSE_BIT];
}
if ((networkEvents.lNetworkEvents & FD_WRITE))
{
WSASetEvent(recvSocketInfo->m_Connected);
*retVal = networkEvents.iErrorCode[FD_WRITE_BIT];
}
}
++it;
}
}
// if error - DoClean, if FD_WRITE (socket is writable) check if m_Connected
// before do any sending
}
}