Sockets – Internet Domains Introduction & TCP vs UDP

 

Chapter 59: Sockets – Internet Domains
Part 1 of 4  |  Internet Domain Sockets – Introduction & TCP vs UDP
AF_INET
IPv4 Domain
AF_INET6
IPv6 Domain
TCP & UDP
Transport Layer

What Are Internet Domain Sockets?

In the previous chapter we studied generic socket concepts and the TCP/IP protocol suite. In this chapter we write real programs using sockets in the IPv4 (AF_INET) and IPv6 (AF_INET6) domains.

An Internet domain socket address is made up of two things: an IP address and a port number. Computers store these as binary numbers, but humans find names much easier to work with. So this chapter also covers how to look up IP addresses from hostnames (using DNS) and port numbers from service names.

Key Terms in This Part

AF_INET AF_INET6 TCP UDP Stream Socket Datagram Socket IP Address Port Number DNS Hostname SOCK_STREAM SOCK_DGRAM

59.1a – Internet Domain Stream Sockets (TCP)

Internet domain stream sockets are built on top of TCP (Transmission Control Protocol). They give you a reliable, bidirectional, byte-stream communication channel.

Think of TCP like a phone call — the connection is established first, data flows in order, and the receiver always gets everything the sender sent.

Client socket(AF_INET, SOCK_STREAM, 0) Server
connect() ── TCP 3-Way Handshake ──> accept()
send() / write() ──── Reliable Data ────> recv() / read()
close() ──── FIN / ACK ────> close()

Properties of TCP Stream Sockets:

  • Data arrives in the same order it was sent
  • No data is lost (TCP retransmits if needed)
  • No duplicates
  • Built-in flow control and congestion control

59.1b – Internet Domain Datagram Sockets (UDP)

Internet domain datagram sockets are built on top of UDP (User Datagram Protocol). Unlike TCP, UDP is connectionless and does not guarantee delivery.

Think of UDP like dropping a letter in a mailbox — it might get there, it might not, and two letters sent together could arrive in any order.

Property UNIX Domain Datagram UDP (Internet Domain)
Reliability ✔ Reliable ✘ Not Reliable
Data Loss Never lost May be lost / duplicated
Order In-order delivery Out-of-order possible
Queue Full Behavior send() blocks Datagram silently dropped
Use Case Local IPC only DNS, VoIP, Games, Streaming

Key difference to remember: If the receiver’s queue is full:

  • UNIX domain datagram: the sender’s send() call blocks until space is available.
  • UDP: the datagram is silently dropped — no error is returned to the sender.

Socket Address Structure for IPv4

Every Internet domain socket needs an address. For IPv4, we use struct sockaddr_in:

#include <netinet/in.h>

struct sockaddr_in {
    sa_family_t    sin_family;   /* AF_INET */
    in_port_t      sin_port;     /* Port number (network byte order) */
    struct in_addr sin_addr;     /* IPv4 address */
};

struct in_addr {
    in_addr_t      s_addr;       /* 32-bit IPv4 address (network byte order) */
};

For IPv6, we use struct sockaddr_in6:

#include <netinet/in.h>

struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* Port number (network byte order) */
    uint32_t        sin6_flowinfo; /* IPv6 flow info */
    struct in6_addr sin6_addr;     /* IPv6 address */
    uint32_t        sin6_scope_id; /* Scope ID */
};

struct sockaddr_in memory layout
sin_family
2 bytes (AF_INET=2)
sin_port
2 bytes (network order)
sin_addr.s_addr
4 bytes (IPv4 address, network order)

A simple TCP server setup looks like:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sfd;
    struct sockaddr_in addr;

    /* Create an IPv4 TCP socket */
    sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    /* Fill in server address */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;         /* IPv4 */
    addr.sin_port   = htons(8080);     /* Port 8080, network byte order */
    addr.sin_addr.s_addr = INADDR_ANY; /* Accept on any local interface */

    /* Bind socket to address */
    if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    /* Start listening */
    if (listen(sfd, 5) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Server listening on port 8080...\n");
    /* accept() loop would go here */

    close(sfd);
    return 0;
}

DNS – Domain Name System (Overview)

Humans use names like www.google.com; computers use IP addresses like 142.250.182.4. DNS is the distributed database that translates between them.

Your App
calls getaddrinfo(“www.example.com”)
Resolver
/etc/resolv.conf
DNS Server
Recursive lookup
IP Address
93.184.216.34

The key function for hostname-to-IP resolution in modern programs is getaddrinfo(), which replaces the older gethostbyname(). It supports both IPv4 and IPv6.

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

/* Prototype */
int getaddrinfo(const char *node,        /* hostname or IP string */
                const char *service,     /* port or service name */
                const struct addrinfo *hints,
                struct addrinfo **res);  /* result linked list */

void freeaddrinfo(struct addrinfo *res);

Example — resolve a hostname:

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main() {
    struct addrinfo hints, *res, *p;
    char ipstr[INET6_ADDRSTRLEN];
    int status;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family   = AF_UNSPEC;   /* Allow IPv4 or IPv6 */
    hints.ai_socktype = SOCK_STREAM; /* TCP */

    status = getaddrinfo("www.example.com", "80", &hints, &res);
    if (status != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 1;
    }

    printf("IP addresses for www.example.com:\n");
    for (p = res; p != NULL; p = p->ai_next) {
        void *addr;
        if (p->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
            addr = &(ipv4->sin_addr);
        } else {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
            addr = &(ipv6->sin6_addr);
        }
        inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
        printf("  %s\n", ipstr);
    }

    freeaddrinfo(res);
    return 0;
}

Interview Questions – Part 1

Q1. What is the difference between AF_INET and AF_INET6?

AF_INET is the address family for IPv4 (32-bit addresses). AF_INET6 is for IPv6 (128-bit addresses). You choose the family when calling socket(). IPv6 was introduced to solve the address exhaustion problem of IPv4.

Q2. What is the key difference between a TCP socket and a UDP socket in terms of reliability?

TCP (SOCK_STREAM) guarantees reliable, ordered, duplicate-free delivery. UDP (SOCK_DGRAM) is unreliable — datagrams may be lost, duplicated, or arrive out of order. TCP achieves reliability through sequence numbers, acknowledgments, and retransmissions.

Q3. What happens when you send a UDP datagram and the receiver’s queue is full?

The datagram is silently dropped. The sender gets no error. This is different from UNIX domain datagram sockets, where the sender’s send() would block until space is available.

Q4. What does INADDR_ANY mean in a socket bind call?

INADDR_ANY (value 0) tells the kernel to bind the socket to all available local network interfaces. This means the server will accept connections on any IP address the machine has, whether it’s 127.0.0.1 (loopback), a LAN address, or a public IP.

Q5. Why is getaddrinfo() preferred over gethostbyname()?

getaddrinfo() supports both IPv4 and IPv6, is reentrant (thread-safe), and handles both name-to-address and service-to-port translation in one call. The older gethostbyname() only handles IPv4 and is not reentrant.

Q6. What structure holds an IPv4 socket address?

struct sockaddr_in defined in <netinet/in.h>. It has three important fields: sin_family (set to AF_INET), sin_port (port in network byte order), and sin_addr.s_addr (IPv4 address in network byte order).

Next: Network Byte Order

Learn about big-endian vs little-endian and the htons/htonl/ntohs/ntohl conversion functions.

Part 2 → Network Byte Order EmbeddedPathashala Home

Leave a Reply

Your email address will not be published. Required fields are marked *