1

I have basic tcp application written in C. It basically sends data to a tcp server. I have connected two PC's with cross cable. I send data from one, and successfully get this data from another one. I have built this mechanism to test If somehow connection broken by unhealty ways (ruptured cable etc.), I want to be informed as client. But things doesn't work as I wanted.If I manually stop tcpserver, client side is informed, but when I start program, connection establishes, data starts to flow, then I unplug the cable, and both sides behaves like nothing happened. Client still sends data with no error, and server still shows the client connected but data flow stops. After a few minutes, I plug cable again, the datas -which considered as sent but not sent- flushes suddenly then program continues normally. How can I detect a broken connection like this? Any help would be appreciated. Here is the code;

#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int main() {
const char* server_name = "192.168.5.2";
const int server_port = 30152;

struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;

// creates binary representation of server name
// and stores it as sin_addr
// http://beej.us/guide/bgnet/output/html/multipage/inet_ntopman.html
inet_pton(AF_INET, server_name, &server_address.sin_addr);

// htons: port in network order format
server_address.sin_port = htons(server_port);

// open a stream socket
int sock;
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    printf("could not create socket\n");
    return 1;
}

// TCP is connection oriented, a reliable connection
// **must** be established before any data is exchanged
if (connect(sock, (struct sockaddr*)&server_address,
            sizeof(server_address)) < 0) {
    printf("could not connect to server\n");
    return 1;
}

// send

// data that will be sent to the server
const char* data_to_send = "HELLO THIS IS DATA!";
while(1)
{
    int err = send(sock, data_to_send, strlen(data_to_send), 0);

    if(err==-1)
    {
        printf("ERROR \n");
        break;
    }
    else
    {
        printf("sent  \n");
        sleep(1);
    }

}
printf("EOP\n");

// close the socket
close(sock);
return 0;
}
Furkan KESKIN
  • 168
  • 3
  • 16
  • Do more tests with a longer time. TCP can take many minutes before it timesout the TCP connection and errors out. Give it 10-15 minutes and measure and measure the time until your send() call errors out. – nos Sep 06 '18 at 11:12
  • 1
    Keepalive can help you to detect broken links (http://www.tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) – qrdl Sep 06 '18 at 11:19
  • @qrdl thank you I think it will work – Furkan KESKIN Sep 06 '18 at 11:30
  • Reduce the send buffer size with setsockopt() and you will be notified in advance with a write/send failure or by a select() informing socket not ready for write. – ulix Sep 06 '18 at 21:38

1 Answers1

4

If the peer of a TCP connection closes the connection, it will lead to a recv call on your end to return 0. That's the way to detect closed (but not broken) connections.

If you don't currently receive anything from the peer, you need to make up a protocol on top of TCP which includes receiving data.

Furthermore, sending might not detect broken connections (like missing cables etc.) directly, as there are a lot of retransmissions and timeouts. The best way is again to implement some kind of protocol overlaying TCP, one that for example contains a kind of "are you there" message which expects a reply. If a reply to the "are you there" message isn't received within some specific timeout, then consider the connection broken and disconnect.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621