Question : Enable tcp_nodelay

Hello Guys,

Can you help shed more light into the above tcp_nodelay , how is that we enabled it to reduce the delay to 0 on a linux machine . Let me know your thoughts on this. TY

Mike

Answer : Enable tcp_nodelay

There is a description here: http://www.redhat.com/docs/en-US/Red_Hat_Enterprise_MRG/1.0/html/Realtime_Tuning_Guide/sect-Realtime_Tuning_Guide-Application_Tuning_and_Deployment-TCP_NODELAY_and_Small_Buffer_Writes.html

Also from the tcp(5) man page:

       TCP_NODELAY
              If set, disable the Nagle algorithm.  This means that segments are always  sent  as
              soon as possible, even if there is only a small amount of data.  When not set, data
              is buffered until there is a sufficient amount to send out,  thereby  avoiding  the
              frequent  sending  of  small packets, which results in poor utilization of the net-
              work.  This option is overridden by TCP_CORK; however, setting this  option  forces
              an explicit flush of pending output, even if TCP_CORK is currently set.

I've written a sample TCP server that sets TCP_NODELAY on the socket. It then sends out data in various sizes from 1 to 8192 bytes. You can compile and run it like this:

$  gcc -o nodelay_test nodelay_test.c
$ ./nodelay_test

Then from another shell you can connect to it like this, using netcat:

$ nc localhost 5678

You can make various timing experiments by enabling/disabling the TCP_NODELAY setting, and  using "time" with nc like this:

$ time nc localhost 5678 > /dev/null

real      0m0.003s
user      0m0.000s
sys      0m0.000s

Of course you can also use it over the network for more interesting results. Just replace localhost with the IP adderss of the machine running the test program. And you can increase the size of the buffer.

Hope that helps!
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
/*
 * TCP_NODELAY server example
 */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/un.h>

#define PORT    5678

//#define dprintf(arg...)
#define dprintf(arg...) printf(arg)

int handle_connection(int client)
{
    char buf[16384];
    int sz = 1;
    int i;

    for (i=0; i<sizeof(buf); i++) {
      buf[i] = '0' + (i & 0x3f);
    }

    for (sz=1; sz<sizeof(buf); sz = sz << 1) {
      dprintf("Sending %d bytes\n", sz);
      if (0 > send(client, buf, sz, 0)) {
	perror("send failed");
	exit(EXIT_FAILURE);
      }
    }
    dprintf("Closing client socket\n");
    close(client);
}

int main()
{
    int listensock, clientsock;
    struct sockaddr_in name;
    struct sockaddr_in clientname;
    int size;
    int pid;
    int opt;

    listensock = socket(PF_INET, SOCK_STREAM, 0);
    if (listensock < 0) {
	perror ("socket");
	exit (EXIT_FAILURE);
    }

    name.sin_family = AF_INET;
    name.sin_port = htons(PORT);
    name.sin_addr.s_addr = htonl(INADDR_ANY);
    
    opt=1;
    setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

    if (bind(listensock, (struct sockaddr *)&name, sizeof(name)) < 0) {
	perror ("bind");
	exit (EXIT_FAILURE);
    }

    if (listen(listensock, 1) < 0) {
	perror("listen");
	exit(EXIT_FAILURE);
    }

    dprintf("Listening on port %d\n", PORT);
    while (1) {
	size = sizeof(clientname);
	clientsock = accept(listensock,
			    (struct sockaddr *) &clientname,
			    &size);
	if (clientsock<0) {
	    if (errno == EAGAIN) {
		fprintf(stderr, "Interrupted\n");
		continue;
	    }
	    perror("accept");
	    exit(EXIT_FAILURE);
	}

	opt=1;
	if (setsockopt(clientsock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int))) {
	  perror ("setsockopt(TCP_NDELAY) failed");
	  exit (EXIT_FAILURE);
	}

	pid = fork();
	if (pid < 0) {
	    perror("fork");
	    exit(EXIT_FAILURE);
	} else if (pid == 0) {
	    handle_connection(clientsock);
	} else {
	    close(clientsock);
	    dprintf("Spawned pid %d for connection from %s\n",
		   pid, inet_ntoa(clientname.sin_addr));
	}
    }
}
Random Solutions  
 
programming4us programming4us