Networking

By the end of this lesson you'll understand how programs talk over a network in C++: when to choose TCP or UDP, the exact order of the BSD socket calls, how a TCP echo client and server exchange bytes, the difference between blocking and non-blocking I/O, and which higher-level libraries (Boost.Asio, POCO) save you from writing it all by hand.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Think of a socket as a telephone . A TCP connection is a phone call : you dial ( connect ), the other side picks up ( accept ), and then every word you speak arrives in order with nothing dropped — the line guarantees it. UDP is more like posting postcards : you scribble a message and drop it in the box (one sendto ), with no call, no guarantee it arrives, and no promise that two cards arrive in the order you sent them — but it's fast and cheap. The port number is the extension you're dialling on a shared building's switchboard (the IP address). Knowing which "phone behaviour" you need is the first decision in any networked program.

1. TCP vs UDP — picking the right pipe

Every networked program starts with one choice: do you need reliability or raw speed ? TCP (Transmission Control Protocol) gives you a reliable, ordered byte stream — the OS resends lost packets and reassembles them in order, so what you send is exactly what arrives. UDP (User Datagram Protocol) skips all that bookkeeping: each datagram is fired off independently, may be lost, and may arrive out of order — but with almost no overhead. You pick the protocol when you create the socket: SOCK_STREAM for TCP, SOCK_DGRAM for UDP.

2. The BSD Sockets API — call order matters

Nearly every language's networking sits on top of the BSD sockets API — a small set of C functions that originated in Berkeley Unix and now run everywhere (Windows calls its near-identical version Winsock ). The functions must be called in a specific order. A server goes socket → bind → listen → accept , then exchanges data and closes. A client is shorter: socket → connect , then exchange and close. The key surprise: accept() returns a brand-new socket dedicated to that one client, leaving the original socket free to accept the next.

3. A TCP Echo Server & Client

The "hello world" of sockets is an echo service: the server sends back whatever the client sends it. Read the server first — note how it checks every return code, sets SO_REUSEADDR , converts the port with htons() , and loops on recv() until the client closes. Then read the matching client. These can't run in the editor (no live network), so the expected exchange is written at the bottom of each example.

Here's the other half. The client creates a socket, connect() s to the server's IP and port, sends a message, and reads the echoed reply. Notice that send() and recv() are not guaranteed to move all the bytes in one call — robust code loops, which we'll lean on in the exercises.

Your turn — and this one runs . After recv() hands you raw bytes, the very first thing real servers do is parse them. Below is the first line of an HTTP request; split it into its three fields with an istringstream . Fill in the blank, then run it.

4. Blocking vs Non-Blocking I/O

By default, socket calls are blocking : recv() pauses your thread until data shows up. That's easy to reason about, but a single slow client stalls the whole thread — so blocking servers typically spawn one thread per connection. Non-blocking sockets return immediately; if nothing is ready, recv() hands back -1 with errno == EWOULDBLOCK instead of waiting. That lets a single thread watch thousands of sockets using an OS "readiness" mechanism — epoll on Linux, kqueue on BSD/macOS, IOCP on Windows. More scalable, but more complex to write correctly.

Another runnable exercise. Because TCP can split or merge your messages, real protocols frame each message with its length, like 5|hello . Build that frame from a payload — fill in the blank to write the length prefix, then run it to watch it decode again.

5. Higher-Level Libraries: Boost.Asio & POCO

Writing raw sockets teaches you what's happening, but in real projects you'll usually reach for a library that smooths over the sharp edges — non-blocking I/O, timeouts, SSL/TLS, and the differences between POSIX and Windows. The two most common in C++ are below.

Boost.Asio is the de-facto standard for high-performance async networking in C++ (and the basis for the proposed std::net ). You hand it work and callbacks (or coroutines), and its io_context event loop drives them — no manual epoll juggling. Great when you need to scale to many concurrent connections or want SSL built in.

POCO (the POrtable COmponents library) offers friendlier, more object-oriented classes like StreamSocket and ServerSocket , plus ready-made HTTP client/server components. It's an easier on-ramp when you want "just give me a working server" without learning an async model first.

Rule of thumb: learn raw sockets once, then let Boost.Asio or POCO handle production. They also hide the Winsock-vs-POSIX gap, so your code stays portable.

No blanks this time — just a brief and an outline. This is the exact job a server does after recv() : turn a line of text into structured fields. It runs in the editor, so build it, run it, and check your output against the comments.

Practice quiz

When should you choose TCP over UDP?

  • When you need every byte to arrive in order without loss (web, files, chat)
  • When you want the lowest possible latency for live video
  • When you never care about ordering
  • When you are sending a single broadcast packet

Answer: When you need every byte to arrive in order without loss (web, files, chat). TCP gives a reliable, ordered byte stream — ideal for web pages, file transfers, and chat where missing data breaks things.

Which socket type creates a TCP socket?

  • SOCK_DGRAM
  • SOCK_STREAM
  • SOCK_RAW
  • SOCK_SEQPACKET

Answer: SOCK_STREAM. TCP uses SOCK_STREAM (a reliable ordered stream); UDP uses SOCK_DGRAM (datagrams).

What is the correct server-side call order in the BSD sockets API?

  • socket, connect, send, recv
  • bind, socket, listen, accept
  • socket, bind, listen, accept
  • listen, bind, socket, accept

Answer: socket, bind, listen, accept. A server goes socket -> bind -> listen -> accept, then exchanges data and closes.

What does accept() return when a client connects?

  • The same listening socket, now connected
  • A brand-new socket dedicated to that one client
  • The client's IP address as a string
  • An error code only

Answer: A brand-new socket dedicated to that one client. accept() returns a new socket for that client, leaving the original listening socket free to accept the next.

What does htons() do, and why is it needed for a port?

  • It hashes the port for security
  • It converts a 16-bit value from host byte order to network (big-endian) order
  • It resolves a hostname to an IP
  • It opens the port in the firewall

Answer: It converts a 16-bit value from host byte order to network (big-endian) order. htons ('host to network short') converts a 16-bit value like a port to network byte order; skipping it corrupts the port on the wire.

Why might recv() return only part of a message?

  • TCP is a byte stream, not a message queue — one send can arrive across several recv calls
  • recv() is buggy and should be avoided
  • The OS limits recv() to 1 byte
  • Because UDP guarantees full messages but TCP does not exist

Answer: TCP is a byte stream, not a message queue — one send can arrive across several recv calls. TCP is a stream: sends can split or merge, so you must loop on recv() into a buffer until you have a complete message.

Parsing the request line 'GET /index.html HTTP/1.1' with iss >> method >> path >> version yields which path value?

  • GET
  • /index.html
  • HTTP/1.1
  • index.html

Answer: /index.html. >> splits on whitespace into three fields: method=GET, path=/index.html, version=HTTP/1.1.

How does a non-blocking recv() behave when no data is ready?

  • It blocks until data arrives
  • It returns -1 with errno == EWOULDBLOCK instead of waiting
  • It returns 0 and closes the socket
  • It throws a C++ exception

Answer: It returns -1 with errno == EWOULDBLOCK instead of waiting. A non-blocking call returns immediately; if nothing is ready, recv() returns -1 with errno EWOULDBLOCK.

Why does a server fail to restart with 'Address already in use'?

  • The port number is invalid
  • The previous socket is still in TIME_WAIT; set SO_REUSEADDR before bind()
  • Another program permanently owns the port
  • You forgot to call listen()

Answer: The previous socket is still in TIME_WAIT; set SO_REUSEADDR before bind(). TCP keeps the port in TIME_WAIT after close; setting SO_REUSEADDR with setsockopt() before bind() lets you reuse it immediately.

Which OS readiness mechanism lets one thread watch thousands of sockets on Linux?

  • epoll
  • kqueue
  • IOCP
  • select only

Answer: epoll. epoll is the Linux mechanism; kqueue is BSD/macOS and IOCP is Windows. They let a single thread scale to many connections.