Skip to main content
  1. Notes/

Sockets (Stream Sockets and Datagram Sockets)

A socket is an endpoint for two-way communication between two programs, typically running on the same machine or across different machines in a network.

There are two main types of sockets:

  • Stream socket (TCP): Uses the Transmission Control Protocol (TCP) to provide a reliable, ordered, and error-checked stream of bytes between two programs. TCP ensures data arrives in the same order it was sent.
  • Datagram socket (UDP): Uses the User Datagram Protocol (UDP), which is connectionless and does not guarantee delivery or ordering of packets. It is faster than TCP but less reliable. Some implementations add timeouts or retries for error handling.

Sockets are identified by a combination of:

  • An IP address (identifies the machine), and
  • A port number (identifies the specific process/service on that machine).

Sockets are accessed through system calls (APIs) provided by the operating system.

Important socket system calls

int socket(int domain, int type, int protocol);
→ Creates a new socket and returns a file descriptor (an integer that identifies the socket).

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); → Associates a socket with an address (IP + port).

int close(int sockfd); → Closes a socket and frees associated resources.

Typical Workflow

Server-Side Flow (TCP)
  1. socket() → create socket.
  2. bind() → assign IP address + port to socket.
  3. listen() → mark as listening for connections.
  4. accept() → accept an incoming connection.
  5. read() / write() → exchange data.
  6. close() → free resources.
Client-Side Flow (TCP)
  1. socket() → create socket.
  2. connect() → connect to server IP + port.
  3. read() / write() → exchange data.
  4. close() → free resources.
TCP socket diagram
UDP Flow (simpler, no connection setup)
  1. socket() → create socket.
  2. bind() → optional, assign local port.
  3. sendto() → send a message to destination.
  4. recvfrom() → receive a message.
  5. close() → free resources.
UDP socket diagram

1. TCP Stream Socket (Connection-Oriented)

TCP is connection-based, meaning the server must listen() for incoming requests and explicitly accept() a client connection before data exchange can occur.

// TCP socket creation
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("Error creating TCP socket");
exit(EXIT_FAILURE);
}

// Fill in server address structure struct sockaddr_in serverAddr{}; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces serverAddr.sin_port = htons(8080); // Port number - source port must be explicitly specified

// Bind to the specified address and port if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { perror(“Bind failed”); close(sockfd); exit(EXIT_FAILURE); }

// Mark socket as passive (ready to accept connections) if (listen(sockfd, 5) < 0) { perror(“Listen failed”); close(sockfd); exit(EXIT_FAILURE); }

// Accept a client connection struct sockaddr_in clientAddr{}; socklen_t clientLen = sizeof(clientAddr); int clientSock = accept(sockfd, (struct sockaddr*)&clientAddr, &clientLen); if (clientSock < 0) { perror(“Accept failed”); close(sockfd); exit(EXIT_FAILURE); }

printf(“TCP connection established!\n”);

2. UDP Datagram Socket (Connectionless)

UDP is connectionless and does not guarantee delivery, ordering, or reliability. However, it is much faster and is often used for real-time applications like online gaming, video streaming, etc.

// UDP socket creation
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("Error creating UDP socket");
exit(EXIT_FAILURE);
}

// Fill in server address structure struct sockaddr_in serverAddr{}; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(8080);

// Bind to the specified address and port if (bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) { perror(“Bind failed”); close(sockfd); exit(EXIT_FAILURE); }

printf(“UDP server listening on port 8080…\n”);

// Receive a datagram from any client char buffer[1024]; struct sockaddr_in clientAddr{}; socklen_t clientLen = sizeof(clientAddr);

int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&clientAddr, &clientLen);

if (n < 0) { perror(“recvfrom failed”); close(sockfd); exit(EXIT_FAILURE); }

buffer[n] = ‘\0’; printf(“Received UDP datagram: %s\n”, buffer);

// Send a reply const char* reply = “Message received!”; sendto(sockfd, reply, strlen(reply), 0, (struct sockaddr*)&clientAddr, clientLen);

Computer Vision

Overview of Computer Vision

Overview of Computer Vision

Core concepts in computer vision and machine learning

cv ml
History of Computer Vision

History of Computer Vision

How computer vision evolved through feature spaces

cv
ImageNet Large Scale Visual Recognition Challenge

ImageNet Large Scale Visual Recognition Challenge

ImageNet's impact on modern computer vision

cv ml
Region-CNNs

Region-CNNs

Traditional ML vs modern computer vision approaches

ml cv

Distributed Systems

Overview of Distributed Systems

Overview of Distributed Systems

Fundamentals of distributed systems and the OSI model

distributed-systems
Distributed Systems Architectures

Distributed Systems Architectures

Common design patterns for distributed systems

distributed-systems
Dependability & Relevant Concepts

Dependability & Relevant Concepts

Reliability and fault tolerance in distributed systems

distributed-systems
Marshalling

Marshalling

How data gets serialized for network communication

distributed-systems
RAFT

RAFT

Understanding the RAFT consensus algorithm

distributed-systems
Remote Procedural Calls

Remote Procedural Calls

How RPC enables communication between processes

distributed-systems
Servers

Servers

Server design and RAFT implementation

distributed-systems
Sockets

Sockets

Network programming with UDP sockets

distributed-systems

Machine Learning (Generally Neural Networks)

Anatomy of Neural Networks

Anatomy of Neural Networks

Traditional ML vs modern computer vision approaches

ml cv
LeNet Architecture

LeNet Architecture

The LeNet neural network

ml cv
Principal Component Analysis

Principal Component Analysis

Explaining PCA from classical and ANN perspectives

data ml

Cryptography & Secure Digital Systems

Symmetric Cryptography

Symmetric Cryptography

covers MAC, secret key systems, and symmetric ciphers

cryptography
Hash Functions

Hash Functions

Hash function uses in cryptographic schemes (no keys)

cryptography
Public-Key Encryption

Public-Key Encryption

RSA, ECC, and ElGamal encryption schemes

cryptography
Digital Signatures & Authentication

Digital Signatures & Authentication

Public-key authentication protocols, RSA signatures, and mutual authentication

cryptography
Number Theory

Number Theory

Number theory in cypto - Euclidean algorithm, number factorization, modulo operations

cryptography
IPSec Types & Properties

IPSec Types & Properties

Authentication Header (AH), ESP, Transport vs Tunnel modes

cryptography