我正在研究一种将传感器数据单向发送到远程服务器的客户端应用程序。初始登录后,服务器没有返回数据。我的问题是当以太网断开连接,例如硬连接断开,即无线链接断开时,我的应用程序在尝试发送'之后没有得到错误返回值。呼叫。我正在使用一个非阻塞套接字实例。线程检查' recv'每个循环使用' select'。它确实最终会在' recv'但永远不要发送'。 当远程PC的互联网连接丢失时,它会导致程序从服务器断开几分钟到几小时,然后才能识别出连接丢失,并切换到重新登录服务器。可以做些什么来帮助检测硬断开?
void checkConnect(NTRIP& server)
{
//1st check for recv or gracefully closed socket
char databuf[SERIAL_BUFFERSIZE];
fd_set Reader, Writer, Err;
TIMEVAL Timeout;
Timeout.tv_sec = 1; // timeout after 1 seconds
Timeout.tv_usec = 0;
FD_ZERO(&Reader);
FD_ZERO(&Err);
FD_SET(server.socket, &Reader);
FD_SET(server.socket, &Err);
int iResult = select(0, &Reader, NULL, &Err, &Timeout);
if(iResult > 0)
{
if(FD_ISSET(server.socket, &Reader) )
{
int recvBytes = recv(server.socket, databuf, sizeof(databuf), 0);
if(recvBytes == SOCKET_ERROR)
{
cout << "socket error on receive call from server " << WSAGetLastError() << endl;
closesocket(server.socket);
server.connected_IP = false;
}
else if(recvBytes == 0)
{
cout << "server closed the connection gracefully" << endl;
closesocket(server.socket);
server.connected_IP = false;
}
else //>0 bytes were received so read data if needed
{
}
}
if(FD_ISSET(server.socket, &Err))
{
cout << "select returned socket in error state" << endl;
closesocket(server.socket);
server.connected_IP = false;
}
}
else if(iResult == SOCKET_ERROR)
{
cout << "ip thread select socket error " << WSAGetLastError() << endl;
closesocket(server.socket);
server.connected_IP = false;
}
//2nd check hard disconnect if no other data has been sent recently
if(server.connected_IP == true && getTimePrecise() - server.lastDataSendTime > 5.0)
{
char buf1[] = "hello";
cout << "checking send for error" << endl;
iResult = send(server_main.socket, buf1, sizeof(buf1), 0);
if(iResult == SOCKET_ERROR)
{
int lasterror = WSAGetLastError();
if(lasterror == WSAEWOULDBLOCK)
{
cout << "server send WSAEWOULDBLOCK" << endl;
}
if(lasterror != WSAEWOULDBLOCK)
{
cout << "server testing connection send function error " << lasterror << endl;
closesocket(server.socket);
server.connected_IP = false;
}
}
else
{
cout << "sent out " << iResult << " bytes" << endl;
}
server.lastDataSendTime = getTimePrecise();
}
}
答案 0 :(得分:1)
在尝试发送内容之前,无法检测断开连接。 您的解决方案如下:
您检测到您在一段时间内未收到任何数据,并且您想检查连接是否处于活动状态。
使用send
功能将一些数据发送到服务器。它可能是特定于协议的ping数据包或垃圾。 send
函数立即返回,因为它不等待实际的数据发送。它只填充内部发送缓冲区。
您开始等待套接字读取。
在您等待时,操作系统会尝试将发送缓冲区中的数据发送到服务器。
当操作系统检测到无法将数据传送到服务器时,连接被标记为错误。
现在,在调用recv
和send
函数时,您会收到错误。
发送超时是系统特定的,可以配置。通常,大约20秒(Linux) - 2分钟(Windows)。这意味着在收到错误之前需要等待很多。
注意:
您也可以启用TCP保持活动机制,但我不建议您这样做。
您还可以修改TCP超时间隔。当您希望连接在临时网络断开连接时仍然有用。
答案 1 :(得分:0)
这就是TCP的工作方式,并且打算工作。您将从后续发送中收到错误,但绝不会在断开连接后从第一次发送中收到错误。在发出错误信号之前,需要克服缓冲,重试和重试超时。