我正在试图弄清楚我正在编写的这个应用程序是否有问题
该应用程序的目标是检测连接在同一LAN上的嵌入式设备是否断开连接。我在stackoverflow上阅读了很多常见问题
由于此嵌入式设备具有在默认端口上运行的Web服务器,因此想法是创建无限循环并在该端口上连续发送消息。如果我检测到错误,我认为主机已断开连接
然而,经过大量研究,在局域网上嗅探数据包等,我发现将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);}
基本上程序运行正常。由于它每秒迭代一次,我不知道它是否真的从O.S.透视原因我不知道这种方式我做错了什么。
此外,我注意到很多开放端口仍处于TIME_WAIT状态,因此我每次将套接字标记为SO_REUSEADDR和SO_LINGER。运行此应用程序3/4小时后,我有〜200个开放端口及时等待
这是对的吗?我应该追随另一种,也许更简单的方式吗?
谢谢大家! ;)
答案 0 :(得分:0)
如果您只检查Web服务器是否存在,则没有理由发送任何内容:仅使用connect()就足以确保目标至少在网络堆栈级别上存活。
为了更加确定目标状态,您可以从Web服务器中查询有用的内容并检查结果。如果服务器支持持久的HTTP连接,它将在服务器上稍微增加一些负载,但可以通过单一连接完成。在这种情况下你最好使用一些HTTP客户端库:正确实现客户端可能会很棘手。
TIME_WAIT没问题,这是正常状态,这种状态会逐渐超时。