UDP/TCP
HTTP vs Socket
HTTP(HyperText Transfer Protocol) is a protocol used to transfer HTML, JSON, and other web content. It operates on a request-response model:
-
The client sends a request,
-
The server replies with a response.
π This means the server can only respond when the client initiates a request, so it is a one-way (half-duplex) communication.
Socket communication supports two-way (full-duplex) communication. Once connected, the client and server can freely exchange data in both directions.
composed of protocol, ip, port number
Commonly used in real-time chat, online games, push notifications, etc.
TCP sockets maintain persistent connections and provide reliable data transfer.
Feature | HTTP | Socket |
---|---|---|
Communication | Request-Response (one-way) | Two-way (full-duplex) |
Connection | Established per request | Persistent connection |
Real-time Support | Low | High |
Typical Use Cases | Web pages, REST APIs | Chat apps, games, real-time apps |
Protocol | HTTP | TCP / UDP |
Network Socket
Socket = Protocol + IP address + Port number
In Unix-like systems, a socket is treated as a type of file, though with some differences in Windows.
Everything is a File (in Unix) Unix systems follow the philosophy that "everything is a file", including not only regular files and directories, but also devices, pipes, and sockets.
Socket as a File Descriptor
When a process creates a socket using
// AF_INET: Adress Familiy meaning IPv4 internet protocol AF_INET6 -> IPv6
// SOCK_STREAM: Socket Type SOCK_STREAM: TCP, SOCK_DGRAM: UDP
// 0: specify protocol 0 means choose default protocol based on prev args in this case TCP
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
the sockfd
returned is a file descriptor, just like the one returned by open() for a regular file.
This allows sockets to be handled using standard I/O system calls
Prepare Server address struct (Client)
process has to notify OS server's IP address & port
// af: AF_INET IPv4 AF_INET IPv6
// src: string based IP addr
// dst: destination for binary translated IP address
//
// return 1 on success 0 on invalid IP addr (format err) -1 on af not supported
int inet_pton(int af, const char *src, void *dst);
Send MSG using socket (Client UDP)
char *message = "Hello, UDP Server!";
ssize_t sent_bytes = sendto(sockfd, message, strlen(message), 0,
(struct sockaddr*)&servaddr, sizeof(servaddr));
if (sent_bytes < 0) {
perror("sendto failed");
}
when sendto()
is called process send data to OS, OS send UDP header + IP header to network interface
- function returns after request (not synchronous)
Receive MSG using socket (Server UDP)
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
char buffer[1024];
ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0,
(struct sockaddr*)&cliaddr, &len);
if (n < 0) {
perror("recvfrom failed");
} else {
buffer[n] = '\0';
printf("Received message: %s\n", buffer);
}
recvfrom()
function copy UDP packet to buffer and return sender's address information
π UDP (User Datagram Protocol)
UDP is a connectionless transport-layer protocol designed for fast and lightweight data transmission.
Unlike TCP, it does not guarantee delivery, order, or error checking β making it ideal for real-time applications like video streaming or online gaming.
π Work Flow
π¨ Sender (Client Side)
-
Create Socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
set server address struct
std::memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port);
-
send message
void UdpClient::sendMessage(const std::string &message) { ssize_t sent = sendto(sock, message.c_str(), message.length(), 0, (sockaddr *)&serverAddr, sizeof(serverAddr)); if (sent < 0) { perror("Send failed"); throw std::runtime_error("Failed to send message"); } }
π₯ Receiver (Server Side)
-
create socket
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
set server address struct
std::memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; // λͺ¨λ IPλ‘λΆν° μμ νμ© serverAddr.sin_port = htons(port);
-
bind
Bind the socket to a local IP and port:
bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
-
Receive MSG
void UdpServer::receiveMessage() { char buffer[BUFFER_SIZE]; sockaddr_in clientAddr; socklen_t clientLen = sizeof(clientAddr); std::memset(buffer, 0, BUFFER_SIZE); ssize_t received = recvfrom(sock, buffer, BUFFER_SIZE - 1, 0, (sockaddr *)&clientAddr, &clientLen); if (received < 0) { perror("recvfrom failed"); return; } buffer[received] = '\0'; // null-terminate the string std::cout << "Received from " << inet_ntoa(clientAddr.sin_addr) << ":" << ntohs(clientAddr.sin_port) << " -> " << buffer << std::endl; }
Error Detection in UDP
-
UDP Checksum UDP provides a checksum field to detect data corruption.
Location: 4th field in the UDP header (16 bits total)
Coverage: UDP header + data + parts of the IP header (pseudo header)
Functionality: The sender calculates the checksum before transmission and inserts it into the header.
The receiver recalculates the checksum on arrival; if the value differs, the packet is considered corrupted.
Optional in IPv4, but mandatory in IPv6.
-
Detection Only, No Recovery UDP can detect errors, but it cannot recover from them.
Corrupted packets are discarded immediately.
No retransmission or correction is provided by UDP.
Applications must implement error-handling, retransmission, and acknowledgment logic if needed.
-
Pseudo Header To increase reliability, UDP includes a pseudo header in the checksum calculation, which contains selected IP layer fields.
Pseudo Header includes: Source IP address
Destination IP address
Protocol number (UDP = 17)
UDP length
This helps detect errors like incorrect destination address during transmission.
π Summary Table
Item | UDP |
---|---|
Checksum | Yes (16-bit) |
Error Detection | Yes |
Error Recovery | No |
Guaranteed Delivery | No |
Retransmission | No |
Handling Missing Packets | Delegated to Application |
Checksum Required in IPv6 | Yes |
π TCP (Transmission Control Protocol)
TCP is a connection-oriented transport-layer protocol that ensures reliable, ordered, and error-checked delivery of data between applications.
Key Concepts
- Connection-oriented: set connection before transfer (3-way handshake)
- Reliability: resend lost packet, remove duplicated packet
- Flow Control: eg: sliding window
- Congestion Control: control transfer speed (eg: AIMD, Slow Start)
π€ 3-Way Handshake (Establish Connection)
- SYN: Client -> Server request connection (including seq number)
- SYN-ACK: Server -> Client respond (My seq + ACK for client seq)
- ACK: Client -> Server
after this data transfer begins
π€ Data Transfer
- TCP divide data into Segments and attach seq number to each segment
- Receiver responde with ACK notifying which data has arrived
- If no ACK resend
- order segments using seq number
β 4-Way HandShake (Close Connection)
- FIN: One side sends a connection termination request (Finish).
- ACK: The other side acknowledges the FIN.
- FIN: The other side also sends its own termination request.
- ACK: The original sender acknowledges the second FIN.
νΉμ§ | TCP | UDP |
---|---|---|
Connection | Connection-based | Connectionless |
Reliabilty | O | X |
Speed | slow | fast |
usage | file transfer, web browsing | streaming, game, voip |
π TCP is Stream
Client send: "12457810111314" but
Server can show
Received from 127.0.0.1:56600 -> 12 Received from 127.0.0.1:56600 -> 457810111314
TCP guarantees order of stream, but does not guarantee size of chunk
user's responsibility to set boundary (eg: multipart form-data, size prefix)
Prefix
attach size header to message [ size ] [ message ]
π Timeout
Connect
if server does not answers connect()
TCP waits and retries -> depends on OS setting
Example on Linux to control this:
/proc/sys/net/ipv4/tcp_syn_retries # Default: 6 retries
Data Transmission
-
send() usually returns immediately once the data is copied to the OS buffer.
-
If the send buffer is full, send() can block or fail depending on socket settings.
-
recv() blocks if no data is available unless you set a timeout (SO_RCVTIMEO).
Automatic retransmission
-
TCP automatically retransmits lost packets inside the kernel if ACKs are not received.
-
This retransmission is invisible to your application β it just experiences delays or connection drop.
Linux controls retransmissions with:
/proc/sys/net/ipv4/tcp_retries2 # Default: 15 retries (can mean several minutes)
After this retry limit is reached without success, TCP closes the connection (RST).
Keepalive
TCP keepalive probes are sent when the connection is idle, to check if the peer is alive.
If keepalive probes fail after a number of retries, TCP closes the connection.
C++ code
Connection
if (connect(sock, (sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
{
perror("Connect failed");
close(sock);
throw std::runtime_error("Failed to connect to server");
}