Skip to content

Instantly share code, notes, and snippets.

@nishidy
Last active April 2, 2019 17:13
Show Gist options
  • Save nishidy/a1a8c829ff24439bbfce4bbd90de123f to your computer and use it in GitHub Desktop.
Save nishidy/a1a8c829ff24439bbfce4bbd90de123f to your computer and use it in GitHub Desktop.
TCP_DEFER_ACCEPT test program for client
#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;
}
@nishidy
Copy link
Author

nishidy commented Apr 2, 2019

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