将Winsocket connect()和send()放入循环中是否正确?
Is it correct to put a Winsocket connect() and send() in a loop?
我想弄清楚我正在编写的这个应用程序是否有问题。
该应用程序的目标是检测连接在同一局域网上的嵌入式设备是否断开连接。一个常见的问题,我在这里读了很多关于stackoverflow。
由于这个嵌入式设备在默认端口上运行一个web服务器,因此我们的想法是创建一个无限循环,并在该端口上不断发送消息。如果我检测到一个错误,我假设主机已断开连接。
然而,经过大量的研究,局域网上的数据包嗅探等,我发现将send()
置于无限循环中与您第一次调用它不同。
原因是当您创建套接字并第一次调用send时,它执行TCP HANDSHAKE
,然后发送消息。但是,在同一个循环中,当send再次被调用时,没有握手,消息只是被发送。因此,如果我在这一刻断开嵌入式设备,发送将再次返回成功,只有在几次尝试后才会失败。类似的情况也发生在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: %un", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
} else
wprintf(L"Set SO_REUSEADDR: ONn");
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: %un", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
} else
wprintf(L"Set SO_LINGER: ONn");
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。运行此应用程序3/4小时后,我有大约200个开放端口。
对吗?我应该遵循另一种更简单的方法吗?感谢所有!div;)
如果您只是检查web服务器是否存在,则没有理由发送任何内容:单独connect()足以确保目标至少在网络堆栈级别上是存活的。
为了更确定目标状态,你可以从web服务器询问一些有用的东西并检查结果。它将稍微增加服务器的负载,但如果服务器支持持久HTTP连接,则可以使用单个连接完成。在这种情况下,你最好使用一些HTTP客户端库:正确实现客户端可能会很棘手。
TIME_WAIT是ok,这是正常状态,这个状态会逐渐超时。
- C++-字符串是否包含一个带有简单循环的单词
- 是否可以在文本文件中找到最长单词的长度,并在同一个文本文件中读取,只需 1 个 while 循环?
- 是否有可能实现O(N)时间和O(1)空间解决方案,以实现C++中的字符串循环移位
- 是否可以在 for 循环中添加两个浮点数?
- 循环中本地对象的析构函数是否保证在下一次迭代之前被调用?
- 我的 if 语句打印在我的 while 循环中的每个 if 语句上,无论它是否为假
- 使用 for 循环是否比在 C++ 中将内容保存在向量中更快?
- 是否可以在一个循环中写入多个二进制文件
- 在C++中,是否可以在单个循环中顺序迭代多个迭代器
- 是否可以禁止在for循环体内部修改循环变量
- 基于C++范围的循环,容器是否被复制
- 是否可以为一个循环设置多个条件
- (C++)for循环中的空初始语句是否保存所有编译器中变量的上一次初始化
- 是否必须使用无限循环来有效地重用协程句柄?
- 是否可以在基于范围的 for 循环中使用模板化的开始/结束方法
- C++是否在 for 循环之前获取参数
- 在 for 循环中声明结构是否合法C++?
- For 循环是否总是至少执行一次?
- 我是否应该避免在循环中的常数之间进行操作
- 我们如何知道 python 代码在 C 或 C++ 中是否处于永无止境的循环中