Skip to main content

Lecture Notes: 19 Network Client

··2 mins

Writing a TCP in C #

Network layers:

  • Machines on the internet have an IP address
  • IP packets are stateless, unreliable, and don’t guarantee order
  • Over IP is TCP, which uses retransmission and buffering to simulate a stream
  • 64k TCP ports

Here’s some starter code mostly generated by an LLM:

```C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAX_BUFFER 1024

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <host> <port>\n", argv[0]);
        exit(1);
    }

    // Create socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        exit(1);
    }

    // Set up server address
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(argv[2]));
    
    if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr) < 0) {
        perror("Invalid address");
        close(sock);
        exit(1);
    }

    // Connect to server
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection failed");
        close(sock);
        exit(1);
    }

    // Send "hello\r\n"
    const char *msg = "GET / HTTP/1.0\r\n\r\n";
    if (send(sock, msg, strlen(msg), 0) < 0) {
        perror("Send failed");
        close(sock);
        exit(1);
    }

    // Receive response
    char buffer[MAX_BUFFER] = {0};
    int bytes_received = recv(sock, buffer, MAX_BUFFER - 1, 0);
    if (bytes_received < 0) {
        perror("Receive failed");
    } else if (bytes_received == 0) {
        printf("Server closed connection\n");
    } else {
        // Ensure buffer is null-terminated and print the response
        buffer[bytes_received] = '\0';
        printf("%s", buffer);
    }

    // Clean up
    close(sock);
    return 0;
}

Using that, we can write a quick and dirty HTTP client.