Skip to Content
Course content

213: Building a Simple TCP Client

Click on the "Edit" button in the top corner of the screen to edit your slide content.

We've talked about the theory of sockets, but the real magic happens when you actually see bytes moving across a wire. To keep this concrete, we aren't just going to send "Hello World" to a void. We're going to build a client that connects to a real web server—example.com—and requests the page headers using a basic HTTP HEAD request. It's a great way to see how a TCP handshake leads to an actual application-layer conversation.

Opening the Socket Door

Before we can talk to a server, we need a socket. Think of this as creating the phone handset before you actually dial the number. I'm using AF_INET because we're sticking with IPv4, and SOCK_STREAM because TCP is a stream-oriented protocol. If we wanted UDP, we'd use SOCK_DGRAM, but for a web request, we need the reliability of TCP.

int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
    perror("Could not create socket");
    return 1;
}

Targeting Example.com

Now we need to tell C where we're going. We use a sockaddr_in struct. I've decided to hardcode the IP for example.com (93.184.216.34) just to keep this lesson focused on the socket logic rather than getting bogged down in DNS resolution with getaddrinfo, which we can cover in a later session.

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = 80; // Standard HTTP port
server.sin_addr.s_addr = inet_addr("93.184.216.34");

The Byte-Order Blunder

Here is where I almost tripped up—and where you probably will too. I initially tried to connect and it failed miserably. Why? Because I passed the port 80 directly. Computers disagree on "Endianness" (the order in which bytes are stored). Network hardware expects "Big Endian," but your x86 machine is likely "Little Endian."

If you just put 80 in there, the network sees a completely different number. I had to wrap the port in htons() (host-to-network short). It's a small function, but forgetting it is a rite of passage in C networking.

// The fix:
server.sin_port = htons(80); 

Establishing the Connection

With our address struct ready, we call connect(). This is where the "Three-Way Handshake" actually happens. The program will hang here for a moment while the OS handles the SYN, SYN-ACK, and ACK packets. If the server is down or the port is blocked, this returns -1.

if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
    perror("Connection failed");
    return 1;
}

Asking for the Headers

Since we're talking to a web server, we have to speak HTTP. We'll send a HEAD request. This tells the server, "I want the metadata (headers), but don't bother sending me the whole HTML page." It keeps our buffer small and our output clean.

char *request = "HEAD / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
send(sock, request, strlen(request), 0);

char buffer[1024];
int bytes_received = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
    buffer[bytes_received] = '\0'; // Null-terminate the string
    printf("Server Response:\n%s\n", buffer);
}

close(sock);

I made sure to null-terminate the buffer manually. recv() doesn't care about C strings; it just dumps raw bytes into your memory. If you try to printf a buffer that isn't null-terminated, you'll end up printing random garbage from your RAM until the program crashes.




📋 Practical Task

Build a TCP Port Checker

Now that you've seen how to connect to a known service, create a small utility program called port_check.c. Your program should take an IP address and a port number as command-line arguments (using argv).

The program should attempt to connect to that specific IP and port. Instead of sending a request, simply report whether the connection was successful or if it failed. This is essentially the core logic of a basic port scanner. Ensure you handle the byte-order conversion for the port provided by the user.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.