0

Here is my test code:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int set_keep_alive(int sockfd) {
    int optval = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) {
        perror("setsockopt");
        close(sockfd);
        return -1;
    }
    int flags = 6;
         if (setsockopt(sockfd , IPPROTO_TCP, TCP_KEEPIDLE, (void *)&flags, sizeof(flags)))
        {
            return -1;
         };

         flags = 3;
         if (setsockopt(sockfd , IPPROTO_TCP,  TCP_KEEPINTVL, (void *)&flags, sizeof(flags)))
         {
            return -1;
         };

         flags = 3;
         if (setsockopt(sockfd , IPPROTO_TCP, TCP_KEEPCNT, (void *)&flags, sizeof(flags)))
         {
            return -1;
        };
    return 0;
}
int main(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "usage: %s <ip> <port>\n", argv[0]);
        return -1;
    }
    char const *IP = argv[1];
    int PORT = atoi(argv[2]);

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    set_keep_alive(fd);
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    inet_pton(AF_INET, IP, &addr.sin_addr);
    int ret;
    ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
    if (ret < 0) {
        printf("connect failed, ret = %d, errno=%d\n", ret, errno);
        perror("");
        return 1;
    }

    for(int i = 0;;i++, sleep(1)) {
        char buf[100];
        sprintf(buf, "hello%d", i%10);
        int ret = send(fd, buf, strlen(buf), MSG_CONFIRM);
        printf("%d,write ret = %d\n", i, ret);
    }
    close(fd);
    return 0;
}

Assume its called client.c

  1. gcc client.c got a.out
  2. In the server, use nc -l -p <PORT>
  3. ./a.out <Server IP> <PORT>: it will print
0,write ret = 6
1,write ret = 6
2,write ret = 6
3,write ret = 6
4,write ret = 6
5,write ret = 6
6,write ret = 6
....
  1. In the server, there is a shell script called port-close.sh which drops newly incoming packets to the port
#!/bin/sh
iptables -I INPUT -p tcp --dport $1 -j DROP

if I run ./port-close.sh <PORT>, in the client, after I wait for 15 seconds (the keep-alive time), still print ret = 6 which means success.

Please note replace <PORT> and <Server IP> to your configuration

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
Divlaker
  • 401
  • 6
  • 16
  • 1
    The server just drops client's packets on the floor. The client has no way of knowing that, other than waiting for an ACK and seeing that it doesn't come back for some time. And that's some *long* time. See [this answer](https://stackoverflow.com/a/71991009/775806). – n. m. could be an AI Jul 24 '23 at 03:47
  • @n.m.willseey'allonReddit I have set the tcp-keep-alive, it works when I use the `select` function when there is no traffic, it can detect the connection is lost. – Divlaker Jul 24 '23 at 03:52
  • 1
    TCP keepalive only controls keepalive packets. In your case keepalive packets will never be sent anyway. Use TCP_USER_TIMEOUT. – n. m. could be an AI Jul 24 '23 at 03:56
  • @n.m.willseey'allonReddit I tried TCP_USER_TIMEOUT, and it fits my need. Many thanks! – Divlaker Jul 24 '23 at 05:23

1 Answers1

0

Sending data successfully does not mean that the data must be received. You prevented the data from getting from the TCP layer to the network. You didn't prevent it from being sent from the application to the TCP layer, which is the sending that succeeded.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Okay, does BSD socket provide some API, to check the TCP layer has successfully sent the data? – Divlaker Jul 24 '23 at 03:22
  • @Divlaker Sort of. But why would the application care exactly how far the data got? The application shouldn't be looking inside the network layers unless you have a very unusual application. What is your outer problem? Do you want to know if the data got through to the other end? If so, ask it. That's what application protocols using TCP are for -- to allow one application to ask another questions and get answers. – David Schwartz Jul 24 '23 at 03:57
  • @DavidSchwartz "*Sort of*"? What does it provide? AFAIK, there is no way to detect that "sent" data is actually transmitted, unless you are directly monitoring the network layer, or the receiver acks reception of the data. – Remy Lebeau Jul 25 '23 at 19:16
  • @RemyLebeau That's why I said "sort of". There are complex ways to do it, but they're not obvious, not direct, and not usually what you want. – David Schwartz Jul 29 '23 at 04:45