TCP Handshake
Example of a basic tcp client server in C compatible with both IPv4 and IPv6.
Added a bit more details on how the tcp handshake behave and how to observe it using tcpdump
.
Basic client server
Server
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Creating socket");
return EXIT_FAILURE;
}
struct sockaddr_in6 addr = {
.sin6_family = AF_INET6,
.sin6_port = htons(9000),
.sin6_addr = { .s6_addr = INADDR_ANY }
};
if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
perror("Binding socket");
return EXIT_FAILURE;
}
if (listen(sockfd, 1) < 0) {
perror("Listening");
return EXIT_FAILURE;
}
printf("Server is listening on port 9000\n");
int clientfd = accept(sockfd, NULL, 0);
if (clientfd == -1) {
perror("Accepting client");
return EXIT_FAILURE;
}
char* msg = "Hello there";
if (write(clientfd, msg, strlen(msg)) < 0) {
perror("Writing to client");
return EXIT_FAILURE;
}
if (close(clientfd) < 0) {
perror("Closing client");
return EXIT_FAILURE;
}
if (close(sockfd) < 0) {
perror("Closing server");
return EXIT_FAILURE;
}
return 0;
}
Client
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Creating socket");
return EXIT_FAILURE;
}
struct sockaddr_in6 addr = { .sin6_family = AF_INET6, .sin6_port = htons(9000) };
inet_pton(AF_INET6, "::1", &addr.sin6_addr);
if (connect(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
perror("Binding socket");
return EXIT_FAILURE;
}
char buf[8192];
if (recv(sockfd, buf, sizeof(buf), 0) < 0) {
perror("Receiving data");
return EXIT_FAILURE;
}
printf("%s\n", buf);
if (close(sockfd) < 0) {
perror("Closing client");
return EXIT_FAILURE;
}
return 0;
}
TCP server
$ gcc -std=c99 -o server server.c
$ gcc -std=c99 -o client client.c
$ ./server&
[1] 16305
Server is listening on port 9000
$ ./client
Hello there
[1] + 16305 done ./server
tcpdump
Flags notation definition can be found in the tcpdump
manual, under the chapter TCP Packets
.
Refer to iana rfc for more information.
S
=SYN
Synchronize sequence numbers (ie. initiates a connection)..
=ACK
Acknowledges received data.P
=PSH
Push data directly to the application (avoid buffering in the tcp stack?).F
=FIN
No more data from sender (ie. close the connection).R
=RST
Reset the connection.U
=URG
Urgent Pointer field.W
=CWR
Congestion Window Reduced.E
=ECE
ECN-Echo.e
=AE
?
$ sudo tcpdump -i lo -w /tmp/captures port 9000
dropped privs to tcpdump
tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
8 packets captured
16 packets received by filter
0 packets dropped by kernel
$ tcpdump -r /tmp/captures
reading from file /tmp/captures, link-type EN10MB (Ethernet), snapshot length 262144
14:57:51.416604 IP6 localhost.43556 > localhost.cslistener: Flags [S], seq 601017080, win 65476, options [mss 65476,sackOK,TS val 3137478573 ecr 0,nop,wscale 7], length 0
14:57:51.416625 IP6 localhost.cslistener > localhost.43556: Flags [S.], seq 3001355905, ack 601017081, win 65464, options [mss 65476,sackOK,TS val 3137478573 ecr 3137478573,nop,wscale 7], length 0
14:57:51.416636 IP6 localhost.43556 > localhost.cslistener: Flags [.], ack 1, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 0
14:57:51.416714 IP6 localhost.cslistener > localhost.43556: Flags [P.], seq 1:12, ack 1, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 11
14:57:51.416723 IP6 localhost.43556 > localhost.cslistener: Flags [.], ack 12, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 0
14:57:51.416733 IP6 localhost.cslistener > localhost.43556: Flags [F.], seq 12, ack 1, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 0
14:57:51.416754 IP6 localhost.43556 > localhost.cslistener: Flags [F.], seq 1, ack 13, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 0
14:57:51.416765 IP6 localhost.cslistener > localhost.43556: Flags [.], ack 2, win 512, options [nop,nop,TS val 3137478573 ecr 3137478573], length 0