I have a C++ application on an IOT device that connects to a server over a TCP socket. The IOT device can be put into airplane mode, lose signal, etc. When this happens, my socket (as reported by netstat) still shows as ESTABLISHED. When my application writes to this socket via send(), everything from the application’s perspective is fine (no error codes). However, I see the send-Q growing in netstat.
When the device comes out of airplane mode or gets a good signal again, the data is never transmitted to the server despite the “ESTABLISHED” connection. Is there any way that I can get this data to send, or will I have to reestablish the socket again? How can I detect that the connection has been broken?
I’ve tried using SO_KEEPALIVE, TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL on the socket, but this hasn’t seemed to help.
This is not the real code, since I can’t post production code on SO
int sock;
int serverPort = 9999;
sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(serverPort);
inet_pton(AF_INET, serverStringAddr.c_str(), &serverAddress.sin_addr);
int sockFlag = 1;
socklen_t flagLen = sizeof(sockFlag);
setsockopt(sock, IPPROTO_TCP, SO_KEEPALIVE, (void *)&sockFlag, flagLen)
// Made arbitrarily low to try to force the socket to fail quickly
int keepcnt = 2;
int keepidle = 2;
int keepintvl = 2;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
setsockopt(g_Sosockcket, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
connect(sock, (SA*)&serverAddress, sizeof(serverAddress));
// ... User does a bunch of socket writing later ... //
send(sock, myPayloadStr.c_str(), strlen(myPayloadStr.c_str()), 0);
// ... Connection dies due to airplane mode ... //
send(sock, myPayloadStr.c_str(), strlen(myPayloadStr.c_str()), 0); // returns 0
After the device goes into airplane mode and does a send(), netstat looks like this (these are not real IP addresses)
/ # netstat | grep 9999
tcp 0 12543 111.222.33.44:34944 12.345.6.78:9999 ESTABLISHED
I never see the socket die or subsequent calls to send() fail.