select を使用して、ネットワーク上の別のホストからの確認応答を待ちますが、常に 0 を返します。同様の質問を持つ他のスレッドを見たことがありますが、それらの問題は常に、fd_set をリセットしていないか、またはselect() の最初のパラメーターに正しい値を渡していません。fd_setをリセットしているため、それが問題の原因であるとは考えられず、msdnによると、明らかに最初のパラメーターがWindowsで無視されます。
while(!done)
{
//send acknowledgment and sequence number
sendto(_clientSocket, buff, 2, 0, (LPSOCKADDR)&_sockAddr, sizeof(SOCKADDR));
//wait for acknowledgment
struct timeval timeout;
timeout.tv_sec = _rttInfo.timeout/1000;
timeout.tv_usec = _rttInfo.timeout * 1000;
fd_set fds;
FD_ZERO(&fds);
FD_SET(_clientSocket, &fds);
//wait for client to send an acknowledgement
//wait for the socket to be ready for reading
int res = select(0, &fds, NULL, NULL, &timeout);
int err = WSAGetLastError();
if(res == 0) //if timed out, retry
{
timedOutCount++;
if(timedOutCount >= MAX_TIMEOUTS)
{
cout << "Handshaking complete _" << endl;
return true;
}
else
{
cout << "Acknowledgement timed out, resending sequence number and acknowledgement" << endl;
continue;
}
}
//下にelse ifステートメントがありますが、そこには行きません
何があっても、この時点では 0 が返されます。クライアントとサーバーがソケットを介して互いに情報を送信しているのを見たので、クライアント側で間違ったアドレスに送信しているとは思いません。select() が待機しているパケットを送信するためのクライアント側のコードは次のとおりです。
buff[0] = _seqNum;
res = sendto(_socket, buff, 2, 0, (LPSOCKADDR) &sa_in, sizeof(SOCKADDR));
この問題を経験したのは私だけではありません。これに対処する方法を知っている人はいますか?
編集: 誰かが _sockAddr が入力されている場所を尋ねたので、ここに含めます: ClientThread クラスがインスタンス化されている場所があり、sockaddr_in が渡されていることがわかります。
while(true)
{
try
{
// Wait for connection
cout << "Waiting for incoming connection... ";
sockaddr_in clientSockAddr;
// int clientSockSize = sizeof(clientSockAddr);
// Listen in on the bound socket:
// hClientSocket = accept(hSocket,
// reinterpret_cast<sockaddr*>(&clientSockAddr),
// &clientSockSize);
unsigned char seqNum = 0;
int addrSize = sizeof(clientSockAddr);
//wait for a connection
int res=0;
//loop until we get a packet that's from someone new
bool blocking = true;
while(blocking)
{
res = recvfrom(hSocket, buff, strlen(buff), 0, (LPSOCKADDR)&clientSockAddr, &addrSize);
bool foundMatch = false;
//check if we're already handling this client. If so, keep blocking. Otherwise, break out of the loop
for(list<ClientThread*>::iterator it = clientList.begin(); it != clientList.end(); it++)
{
//compare network addresses
if((*it)->GetSockAddr().sin_addr.S_un.S_addr == clientSockAddr.sin_addr.S_un.S_addr)
{
foundMatch = true;
break;
}
}
if(!foundMatch)
{
blocking = false;
}
}
err = WSAGetLastError();
// Check if we can create a new client thread
if(res != SOCKET_ERROR && res != 0)
{
seqNum = (unsigned char) buff[0]; //get the sequence number for handshaking
cout << "accepted connection from: " << GetHostDescription(clientSockAddr) << endl;
//start a client thread, to handle requests from this client.
ClientThread* pThread = new ClientThread(hSocket, clientSockAddr, this, seqNum);
clientList.push_back(pThread);
pThread->start();
}
// if (hClientSocket==INVALID_SOCKET)
// throw "accept function failed.";
}
catch(char* ex)
{
cerr << "\nError: " << ex << endl;
bSuccess = false;
}
}
Edit2: さらにデバッグすると、select ではなく recvfrom の呼び出しでメッセージが受信されるため、sendto の呼び出しが目的のターゲットに到達していることがわかりました。ただし、非ブロッキング呼び出しを使用できるようにする必要があります。