【发布时间】:2015-11-08 22:28:13
【问题描述】:
我正在开发一个客户端应用程序,它以一种方式将传感器数据发送到远程服务器。初次登录后,服务器没有返回数据。我的问题是当以太网断开连接时,例如硬断开连接,即无线链路断开,我的应用程序在尝试“发送”调用后没有得到错误返回值。我正在使用单个非阻塞套接字实例。线程使用'select'检查每个循环的'recv'。它最终会在“recv”上出现错误,但在“send”上不会出现错误。 当远程 PC 出现 Internet 连接丢失时,它会导致程序与服务器断开连接数分钟到数小时,然后才能识别出连接丢失并切换到重新登录服务器。可以做些什么来帮助检测硬断开连接?
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();
}
}
【问题讨论】:
-
TCP 基于连接可靠的假设。这使得它非常非常高效,您可以转储一堆数据以使用 send() 进行传输,并且协议栈会尽其所能来交付该数据。后来,不要让你的程序陷入困境。您不必等待,直到收到“好的,它到了”确认。非常重要的是,延迟会杀死 perf dead。这当然意味着“它不再起作用”的消息也会延迟传递。在调用 shutdown() 之前,您无法确定。
标签: c++ sockets tcp-ip winsock2