Last active
April 2, 2019 17:13
-
-
Save nishidy/a1a8c829ff24439bbfce4bbd90de123f to your computer and use it in GitHub Desktop.
TCP_DEFER_ACCEPT test program for client
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> //printf(), fprintf(), perror() | |
#include <sys/socket.h> //socket(), connect(), recv() | |
#include <arpa/inet.h> // struct sockaddr_in, struct sockaddr, inet_ntoa(), inet_aton() | |
#include <stdlib.h> //atoi(), exit(), EXIT_FAILURE, EXIT_SUCCESS | |
#include <string.h> //memset() | |
#include <unistd.h> //close(), sleep() | |
#include <linux/tcp.h> //TCP_DEFER_ACCEPT | |
#define MSGSIZE 32 | |
#define MAX_MSGSIZE 1024 | |
#define BUFSIZE (MSGSIZE + 1) | |
int main(int argc, char *argv[]){ | |
int clientSock; | |
struct sockaddr_in servSockAddr; | |
char sendBuffer[BUFSIZE]; | |
char recvBuffer[BUFSIZE]; | |
int byteRcvd; | |
int defer = 1; | |
if((clientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ | |
perror("socket() failed"); | |
exit(EXIT_FAILURE); | |
} | |
memset(&servSockAddr, 0, sizeof(servSockAddr)); | |
servSockAddr.sin_family = AF_INET; | |
servSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); | |
/* | |
* host = gethostbyname("DNS"); | |
* if(host != NULL){ | |
* servSockAddr.sin_addr.s_addr = *(unsigned int *)host->h_addr_list[0]; | |
* } | |
*/ | |
servSockAddr.sin_port = htons(8080); | |
setsockopt(clientSock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &defer, sizeof(defer) ); | |
if(connect(clientSock, (struct sockaddr*) &servSockAddr, sizeof(servSockAddr)) < 0){ | |
perror("connect() failed."); | |
exit(EXIT_FAILURE); | |
} | |
printf("connect to %s\n", inet_ntoa(servSockAddr.sin_addr)); | |
sleep(1); | |
sprintf(sendBuffer, "%s", "GET / HTTP/1.1\r\nHost: localhost"); | |
if(send(clientSock, sendBuffer, MSGSIZE, 0) <= 0){ | |
printf("%s\n",sendBuffer); | |
} | |
if(recv(clientSock, recvBuffer, MSGSIZE, 0) < 0){ | |
printf("recv() failed."); | |
exit(EXIT_FAILURE); | |
} | |
printf("received: %s\n",recvBuffer); | |
return 0; | |
} |
If I remove sleep(1) right after connect(), we can find that the first data packet is sent with the final ACK. (piggybacking)
$ grep sleep client.c
#include <unistd.h> //close(), sleep()
//sleep(1);
$ gcc client.c -o client
$ ./client
connect to 127.0.0.1
received: HTTP/1.1 200 OK
$ sudo tcpdump -i lo tcp port 8080
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
17:07:14.709483 IP localhost.47208 > localhost.webcache: Flags [S], seq 2354986443, win 43690, options [mss 65495,sackOK,TS val 408030044 ecr 0,nop,wscale 7], length 0
17:07:14.709493 IP localhost.webcache > localhost.47208: Flags [S.], seq 3089570465, ack 2354986444, win 43690, options [mss 65495,sackOK,TS val 408030044 ecr 408030044,nop,wscale 7], length 0
17:07:14.709609 IP localhost.47208 > localhost.webcache: Flags [P.], seq 1:33, ack 1, win 342, options [nop,nop,TS val 408030044 ecr 408030044], length 32: HTTP: GET / HTTP/1.1
17:07:14.709622 IP localhost.webcache > localhost.47208: Flags [.], ack 33, win 342, options [nop,nop,TS val 408030044 ecr 408030044], length 0
17:07:14.712511 IP localhost.webcache > localhost.47208: Flags [P.], seq 1:16, ack 33, win 342, options [nop,nop,TS val 408030047 ecr 408030044], length 15: HTTP: HTTP/1.1 200 OK[!http]
17:07:14.712650 IP localhost.47208 > localhost.webcache: Flags [F.], seq 33, ack 16, win 342, options [nop,nop,TS val 408030047 ecr 408030047], length 0
17:07:14.712688 IP localhost.webcache > localhost.47208: Flags [F.], seq 16, ack 34, win 342, options [nop,nop,TS val 408030047 ecr 408030047], length 0
17:07:14.712699 IP localhost.47208 > localhost.webcache: Flags [.], ack 17, win 342, options [nop,nop,TS val 408030047 ecr 408030047], length 0
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
TCP_DEFER_ACCEPT on connecting at client side delays final ACK until the first data packet is sent.
However, it only waits up to 200 ms.