Я пытаюсь выяснить, если я делаю что-то не так с этим приложением, я кодирую.Цель приложения - обнаружить, отключаются ли встроенные устройства, подключенные к той же локальной сети.Распространенная проблема, о которой я много читал здесь на stackoverflow.Поскольку у этого встроенного устройства есть веб-сервер, работающий на порте по умолчанию, идея состояла в том, чтобы создать бесконечный цикл и непрерывно отправлять сообщение на этот порт.Если я обнаружу ошибку, я предполагаю, что хост отключен.Однако после многих исследований, перехвата пакетов в локальной сети и т. Д. Я обнаружил, что помещение send()
в бесконечный цикл не было таким же, как если бы вы вызывали его в первый раз.Причина в том, что когда вы создаете сокет и впервые вызываете send, он выполняет TCP HANDSHAKE
, а затем отправляет сообщение.Но в том же цикле, когда снова вызывается send, HANDSHAKE не происходит, и сообщение просто отправляется.Таким образом, если я отключу встроенные устройства в этот момент, отправленный вернется снова успешно, и только после нескольких попыток это не удастся.Аналогичная ситуация происходит с recv()
.Таким образом, мое реальное решение было заключить в бесконечный цикл ВЕСЬ процесс сокета (creation,connection,send,destruction)
.Вот что я сделал в итоге:
while(true){
SOCKET ConnectSocket = INVALID_SOCKET;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
cout <<"socket failed with error: "<< WSAGetLastError();
WSACleanup();
return 0;
}
iResult= ioctlsocket(ConnectSocket,FIONBIO,&ulMode);
if (iResult != NO_ERROR)
cout<<"ioctlsocket failed with error: "<<iResult<<endl;
iResult= setsockopt(ConnectSocket,SOL_SOCKET,SO_REUSEADDR,(char *) &bOptVal,bOptLen);
if (iResult == SOCKET_ERROR) {
wprintf(L"setsockopt for SO_REUSEADDR failed with error: %u\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
} else
wprintf(L"Set SO_REUSEADDR: ON\n");
iResult= setsockopt(ConnectSocket,SOL_SOCKET, SO_LINGER, (char FAR*)&linger, sizeof(linger));
if (iResult == SOCKET_ERROR) {
wprintf(L"setsockopt for SO_LINGER failed with error: %u\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
} else
wprintf(L"Set SO_LINGER: ON\n");
if(connect( ConnectSocket,(SOCKADDR*) &saServer, sizeof(saServer))==SOCKET_ERROR){
cout <<WSAGetLastError()<<endl;
if(WSAGetLastError() == WSAEWOULDBLOCK)
{
fd_set fsConnect;
FD_ZERO(&fsConnect);
FD_SET(ConnectSocket, &fsConnect);
timeval sTimeoutVal;
sTimeoutVal.tv_sec = (long)2;
sTimeoutVal.tv_usec = (long)0;
int retval = select(FD_SETSIZE, (fd_set *) NULL, &fsConnect, (fd_set *)
NULL, &sTimeoutVal);
if(retval != 1)
{
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
} else{
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
}
int iBytes = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
shutdown(ConnectSocket,SD_SEND);
closesocket(ConnectSocket);
if(iBytes == -1 || iBytes != (int)strlen(sendbuf))
{
//send failed machine went down
WSACleanup();
return 1;
}
Sleep(1000);}
В основном программа работает нормально.Так как он повторяется каждую секунду, я не знаю, действительно ли это правильно с точки зрения ОС, потому что я не знаю, так ли я поступаю неправильно.Более того, я заметил, что многие открытые порты остались в состоянии TIME_WAIT, поэтому по этой причине я каждый раз отмечаю сокет как SO_REUSEADDR и SO_LINGER.У меня ~ 200 открытых портов во времени ожидания после 3/4 часов работы этого приложения.Это правильно?Должен ли я следовать другим, может быть, более простым путем?Спасибо всем!;)