0

I have a simple TCP client-server example. Server just for receiving data. The server side logic is:

#define LISTEN_PORT 31337
#define BUFFER_SIZE 4096
//#define QUICKACK

void main () {
     int buflen = 6000, opt_val = 1;
     int server_fd, client_fd, err;
     struct sockaddr_in server, client;
     char buf[BUFFER_SIZE] = {0};

     server_fd = socket(AF_INET, SOCK_STREAM, 0);
     if (server_fd < 0) {
          perror("SOCKET");
          return;
     }

     server.sin_family = AF_INET;
     server.sin_port = htons(LISTEN_PORT);
     server.sin_addr.s_addr = htonl(INADDR_ANY);

     if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val) < 0) {
          perror ("SETSOCKOPT");
          return;
     }

     if (bind(server_fd, (struct sockaddr *) &server, sizeof(server)) < 0) {
          perror("BIND");
          return;
     }

     if (listen(server_fd, 128)) {
          perror("LISTEN");
          return;
     }

     printf("Server is listening on %d\n", LISTEN_PORT);

     for(;;) {
          socklen_t client_len = sizeof(client);
          client_fd = accept(server_fd, (struct sockaddr *) &client, &client_len);
          if (client_fd < 0) {
               perror("ACCEPT");
               return;
          }

          if (setsockopt(client_fd, SOL_SOCKET, SO_RCVBUF, &buflen, sizeof(int)) < 0) {
               perror ("SETSOCKOPT");
               return;
          }

#ifdef QUICKACK
          if (setsockopt(client_fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int)) < 0) {
               perror ("SETSOCKOPT");
               return;
          }
#endif

          for (;;) {
               int read = recv(client_fd, buf, BUFFER_SIZE, 0);
#ifdef QUICKACK
               if (setsockopt(client_fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int)) < 0) {
                    perror ("SETSOCKOPT");
                    return;
               }
#endif

               if (!read) break;
               if (read < 0)
                    perror("READ");
               printf("%s\n", buf);
          }
     }
     return;
}

Then I connect with client or nc and see some strange behavior in tcpdump like:

<-[SYN] win 43690

->[SYN,ACK] win 43690

<-[ACK] win 43690

<-[PSH,ACK] win 43690, length 79

<-[PSH,ACK] win 43690, length 79

->[ACK] ack 159, win 43532

So I can conclude that none of setsockopt()'s worked for me. I tried to disable window scaling (sysctl -w net.ipv4.tcp_window_scaling=0) but that didn't help.

Related: 1, 2

z0lupka
  • 236
  • 4
  • 19
  • 1
    `recv();`??? If that's your actual code, you're invoking undefined behavior. If that's not your actual code, **post your actual code**. – Andrew Henle Sep 23 '19 at 11:34
  • Read the documentation. The buffer size you supply is a hint. The implementation can adjust it up or down. And why would you want to *decrease* the socket receive buffer size? 1024 was known to be too small over 30 years ago. – user207421 Sep 23 '19 at 11:41
  • @user207421 I want to decrease just for testing purposes. Can you give a link? There is nothing about *a hint* in man page. And what's wrong with `QUICK_ACK`? Is it a hint too? – z0lupka Sep 23 '19 at 11:51
  • 1
    See *man 7 tcp.* – user207421 Sep 23 '19 at 23:17
  • 1
    *friendly and kindly comment:* @user207421 Could you explain some not obvious things about `SO_RCVBUF` influence on TCP window size? – z0lupka Sep 25 '19 at 13:27
  • @user207421 I understand that it's much easier to flag comments, but still. – z0lupka Sep 25 '19 at 13:30

0 Answers0