BSCS students who need to actually open a socket and move bytes over TCP or UDP — not just describe the OSI model on an exam — can work through “Beej’s Guide to Network Programming” by Brian “Beej Jorgensen” Hall, a free, self-published guide to the Unix Berkeley sockets API in C. It assumes solid working C (structs, pointers) but zero prior networking knowledge, and builds from what a socket even is through complete, runnable client-server programs, IPv4-to-IPv6 porting, and the non-blocking I/O and data-serialization techniques a real network program actually needs.
The guide is actively and continually maintained directly by its author at beej.us — its public revision history reaches version 3.1.5 with recent fixes covering a memory leak, Windows Subsystem for Linux (WSL) support, and IPv6 datagram behaviour — and it is free in both HTML and PDF form under a CC BY-NC-ND 3.0 licence, with every example C program separately released to the public domain. That combination of genuine depth, runnable code, and decades of continuous upkeep is exactly why it remains one of the most recommended free resources anywhere for learning sockets programming, rather than a reworded textbook chapter on networking theory.
Book Overview
| Course | Network Programming / Sockets Programming in C — TCP/UDP, IPv4/IPv6, the Unix Berkeley sockets API |
| Degree Programs | BSCS |
| Level | University level — assumes working knowledge of C (structs, pointers); no prior networking experience needed |
| Edition | Continually revised HTML/PDF guide (source revision history reaches version 3.1.5) |
| Author(s) | Brian “Beej Jorgensen” Hall |
| Structure | 9 sections: About This Guide, What Is a Socket?, IP Addresses/Structs/Data Munging, Jumping from IPv4 to IPv6, System Calls or Bust, Client-Server Background, Slightly Advanced Techniques, Common Questions, and an Appendix of 24 condensed man pages |
| Exercises | No formal end-of-chapter problem sets; the guide teaches entirely through runnable example C programs (server.c, client.c, talker.c, listener.c, pollserver.c, selectserver.c and others), which this page’s Important Questions and Practice Tips are built to extend |
| Language | English |
| License | CC BY-NC-ND 3.0 (guide text); all example C source code is separately released to the public domain |
| Format | Free HTML and PDF, self-published by the author; no print edition required to use it |
Chapter List
Chapter 1: About This Guide
Difficulty: Easy · Key topics: audience, supported platforms, C99, licence terms, translations
Beej’s Guide opens by setting expectations rather than diving into code: it is written for a competent C programmer who already understands structs and pointers but has never touched the sockets API, and it favors the widest possible platform coverage over showing off one operating system’s extensions, so the examples target the portable Unix sockets API that also works, with small caveats, under Windows and WSL. The chapter states the guide’s own licence up front (Creative Commons Attribution-NonCommercial-NoDerivatives 3.0), grants the example C source code to the public domain separately, and explicitly invites free classroom use and community translation, which is why the guide exists as a continuously revised, versioned document rather than a fixed one-off release.
Key Points:
- Assumes working C knowledge (structs, pointers) but zero prior networking/sockets knowledge
- Guide text is licensed CC BY-NC-ND 3.0; every example C source file is separately public domain
- Targets portable POSIX-style sockets, with a dedicated note for Windows/WinSock and WSL users
- The guide uses semantic version numbers (e.g. 3.1.5) and keeps a full public revision history
- Free for educators to distribute to students without asking permission
- Community translations are explicitly permitted as the one exception to “No Derivative Works”
Memory Tip: Skim the version history at the top of the guide’s source before you start — it tells you exactly which recent fixes (for example the freeaddrinfo() memory leak or the datagram AF_UNSPEC fix) apply to the code you are about to copy.
Common Mistake: Skipping the platform note and jumping straight to socket(), then losing time to a missing <winsock.h> compile error on Windows that this chapter already warns about.
Important Questions:
- Who is Beej’s Guide to Network Programming written for? A reader who already knows C (comfortable with structs and pointers) but has never used the Unix sockets API before; it is not a C language tutorial.
- What is the licence split between the guide’s text and its example code? The prose is CC BY-NC-ND 3.0 (Attribution-NonCommercial-NoDerivatives), while every C example in the guide is explicitly released into the public domain.
Chapter 2: What Is a Socket?
Difficulty: Easy · Key topics: file descriptors, socket(), send()/recv(), SOCK_STREAM vs SOCK_DGRAM, OSI model, data encapsulation
This chapter defines a socket the way Unix does: just another file descriptor, opened with socket() instead of open(), through which data moves with send() and recv() instead of plain read()/write(). It draws the core distinction the rest of the guide depends on — reliable, ordered SOCK_STREAM sockets (used by TCP) versus connectionless SOCK_DGRAM sockets (used by UDP) that can arrive out of order, duplicated, or not at all. A “Low Level Nonsense” section, explicitly marked skippable, then walks through data encapsulation and the seven-layer OSI model, showing how each protocol wraps the payload in its own header on the way out and strips it back off on the way in.
Key Points:
- A socket is just a Unix file descriptor obtained via
socket()instead ofopen() SOCK_STREAMsockets are TCP: reliable, two-way, ordered byte streamsSOCK_DGRAMsockets are UDP: connectionless, unordered, no delivery guarantee- Stream sockets suit long-lived connections; HTTP servers are a classic example
- Data encapsulation wraps a packet in a new header at every OSI layer as it goes out
- The kernel builds the Transport and Internet layer headers for you automatically
- The seven OSI layers: Application, Presentation, Session, Transport, Network, Data Link, Physical
Memory Tip: “Stream is a phone call, Datagram is a postcard” — a stream socket holds a connection open and guarantees order like a call; a datagram fires off one packet with no guarantee it arrives, like a postcard.
Common Mistake: Assuming UDP datagrams always arrive, arrive once, or arrive in order — the guide is explicit that none of those three things is guaranteed with SOCK_DGRAM, so a program using UDP must handle loss or duplication itself.
Important Questions:
- What is the difference between
SOCK_STREAMandSOCK_DGRAMsockets?SOCK_STREAM(TCP) is a reliable, ordered, two-way byte stream between two connected endpoints;SOCK_DGRAM(UDP) sends individual, connectionless packets with no guarantee of delivery, order, or duplicate-free arrival. - Why does the guide explain data encapsulation even though most programmers never touch it directly? Because every
send()orsendto()call is automatically wrapped by the kernel in Transport, Internet and Data Link layer headers, and understanding that layering explains why socket-level code never has to build raw packet headers by hand.
Chapter 3: IP Addresses, Structs, and Data Munging
Difficulty: Medium · Key topics: IPv4/IPv6 addresses, subnets, ports, byte order, struct addrinfo, struct sockaddr, inet_pton()/inet_ntop(), NAT
This is the guide’s first real code chapter, and it works through every data structure the sockets API expects before any system call is introduced. It covers IPv4’s 32-bit dotted addresses versus IPv6’s 128-bit hex addresses (and why IPv6 exists at all), subnet masks, and the port number that identifies a service on a host. It then explains network byte order (Big-Endian) versus a machine’s own host byte order and the htons()/htonl()/ntohs()/ntohl() family used to convert between them, before laying out struct addrinfo, struct sockaddr, struct sockaddr_in and struct sockaddr_in6 — the structures getaddrinfo() fills in for you. It closes with inet_pton()/inet_ntop() for converting addresses to and from text, and a look at reserved private (NAT) address ranges.
Key Points:
- IPv4 addresses are 4 bytes (“dotted quad”); IPv6 addresses are 16 bytes, written in hex-and-colons
- Network Byte Order is Big-Endian; use
htons()/htonl()before sending,ntohs()/ntohl()after receiving struct addrinfois whatgetaddrinfo()fills out; it links viaai_next- A
struct sockaddr_in*can be safely cast to and fromstruct sockaddr* inet_pton()converts a text IP address to binary;inet_ntop()converts it backinet_addr(),inet_aton()andinet_ntoa()are obsolete IPv4-only predecessors- Private/NAT ranges:
10.x.x.x,172.16–31.x.x,192.168.x.x(IPv4), andfd00::/8(IPv6)
Practice Tip: Write a five-line program that calls inet_pton() on “127.0.0.1”, then immediately inet_ntop()s the result back to a string and prints it — seeing the round trip work is the fastest way to stop being intimidated by these structs.
Common Mistake: Forgetting to convert numbers to network byte order with htons()/htonl() before putting them in a struct sockaddr_in field like sin_port, which silently binds to or connects on the wrong port on little-endian machines.
Important Questions:
- Why must fields like
sin_portbe converted withhtons()before use? Because the sockets API always expects multi-byte values in Network Byte Order (Big-Endian), and most desktop/server CPUs (x86) store numbers in Little-Endian Host Byte Order, so an unconverted value is read backwards. - What does
struct addrinfo’sai_nextfield represent, and why does it matter?getaddrinfo()can return more than one valid address for the same hostname (for example one IPv4 and one IPv6), so it returns a linked list;ai_nextpoints to the next result, and correct code should loop through the list rather than assume the first entry always works.
Chapter 4: Jumping from IPv4 to IPv6
Difficulty: Easy · Key topics: AF_INET6, in6addr_any, inet_pton(), getaddrinfo(), dual-stack porting checklist
A short, deliberately practical checklist chapter for a reader who has already written IPv4 code and just wants to know exactly what to change to make it IPv6-capable. It lists each substitution in order: use getaddrinfo() instead of hand-packing structures, swap AF_INET/PF_INET for AF_INET6/PF_INET6, replace struct sockaddr_in with struct sockaddr_in6, swap INADDR_ANY for in6addr_any (or the IN6ADDR_ANY_INIT initializer), and use inet_pton()/inet_ntop()/getnameinfo() instead of the obsolete IPv4-only address functions. It ends by noting that INADDR_BROADCAST has no IPv6 equivalent — multicast replaces it.
Key Points:
- Prefer
getaddrinfo()over hand-coding structs; it keeps code IP-version-agnostic automatically AF_INETbecomesAF_INET6;PF_INETbecomesPF_INET6struct sockaddr_inbecomesstruct sockaddr_in6(nosin6_zerofield)INADDR_ANYbecomesin6addr_any, orIN6ADDR_ANY_INITas a static initializerinet_aton()/inet_addr()becomeinet_pton();inet_ntoa()becomesinet_ntop()gethostbyname()/gethostbyaddr()becomegetaddrinfo()/getnameinfo()INADDR_BROADCASThas no IPv6 equivalent; IPv6 uses multicast instead
Memory Tip: Almost every substitution in this chapter is “add a 6” — sockaddr_in6, in6addr_any, AF_INET6; the one exception worth memorizing separately is that broadcast disappears entirely under IPv6.
Common Mistake: Porting code to IPv6 by changing AF_INET to AF_INET6 everywhere without also switching struct sockaddr_in to struct sockaddr_in6, which compiles but corrupts the address because the two structs have different, incompatible layouts.
Important Questions:
- What is the single change that removes the most IPv4-specific code when porting to IPv6? Switching to
getaddrinfo()for all address setup, since it fills out the correct structures for whichever address family it is asked for and removes the need for manual, version-specific struct packing. - Why can’t
INADDR_BROADCASTbe used under IPv6? IPv6 does not support broadcast at all; the guide’s answer is to use IPv6 multicast instead, which serves a similar purpose without flooding every host on the network.
Chapter 5: System Calls or Bust
Difficulty: Medium · Key topics: getaddrinfo(), socket(), bind(), connect(), listen(), accept(), send()/recv(), sendto()/recvfrom(), close()/shutdown()
The guide’s core reference chapter walks through every system call needed to open a connection and move data, in the order a real program calls them. getaddrinfo() fills in the address structures; socket() turns one of those results into a file descriptor; a server then bind()s it to a local port, listen()s for incoming connections, and accept()s each one, which hands back a brand-new file descriptor for that single connection while leaving the original still listening; a client instead calls connect() directly. Once a connection exists, send()/recv() move stream data, sendto()/recvfrom() move datagrams, and close()/shutdown() end the conversation, with getpeername() and gethostname() available to identify who is on the other end.
Key Points:
getaddrinfo()replaces the obsoletegethostbyname(); it does DNS and service-name lookup and fills instruct addrinfofor yousocket()takes(domain, type, protocol)and returns a file descriptor, or-1on errorbind()associates a socket with a local port; used by servers, rarely by clientslisten()marks a stream socket ready to accept incoming connections, with a backlog queue sizeaccept()blocks until a connection arrives, then returns a new file descriptor for just that connectionsend()/recv()are for connectedSOCK_STREAMsockets;sendto()/recvfrom()are for connectionlessSOCK_DGRAMsocketsshutdown()can close just the read or write half of a connection;close()ends it completely
Practice Tip: Type in the accept() example from this chapter, run it, and telnet to its port from a second terminal window — watching a brand-new file descriptor appear from accept() while the original listening socket keeps running is the moment this chapter actually clicks.
Common Mistake: Using send()/recv() on a SOCK_DGRAM socket or sendto()/recvfrom() on a connected SOCK_STREAM socket — the call families are not interchangeable, and mixing them causes confusing errors instead of an obvious compile-time mistake.
Important Questions:
- Why does
accept()return a different file descriptor than the one passed tolisten()? Because the original socket must keep listening for new incoming connections, soaccept()hands back a fresh socket descriptor dedicated to that one client, letting the server handle many clients from a single listening socket, typically viafork(). - What is the difference between
close()andshutdown()on a connected socket?close()ends the connection and frees the file descriptor entirely;shutdown()can selectively disable just the read side, just the write side, or both while optionally keeping the descriptor open, which matters for programs that still need to finish reading after they stop writing.
Chapter 6: Client-Server Background
Difficulty: Medium · Key topics: client-server model, fork(), stream server/client (server.c, client.c), datagram sockets (talker.c, listener.c)
This chapter turns the previous chapter’s system calls into two complete, runnable programs. server.c listens on a port, accept()s a connection, sends the string “Hello, world!” and, in a real deployment, fork()s a child process per client so the parent can keep accepting new connections. client.c connects to that server and recv()s the greeting — testable directly against server.c with telnet. The chapter then covers the datagram equivalent with talker.c and listener.c, a UDP pair that deliberately uses IPv6 specifically to avoid the address-family mismatch that would otherwise silently drop connectionless packets between an IPv4 sender and an IPv6 listener.
Key Points:
- The classic client-server pattern: one server process, many client connections, usually handled via
fork()per connection server.cdemonstratesbind()+listen()+accept()end-to-end and can be tested with a plaintelnetclientclient.cdemonstratesgetaddrinfo()+socket()+connect()+recv()end-to-endtalker.candlistener.care theSOCK_DGRAM(UDP) equivalent ofclient.c/server.clistener.cusesrecvfrom()to capture the sender’s address along with the datatalker.candlistener.care deliberately locked toAF_INET6to sidestep a v4/v6 address-family mismatch- A UDP server needs no
listen()/accept()step at all —recvfrom()alone is sufficient
Practice Tip: Build and run server.c and client.c against each other on localhost first, then talker.c and listener.c — seeing recv() (stream) and recvfrom() (datagram) fetch data two different ways is the clearest side-by-side lesson in the whole guide.
Common Mistake: Forgetting that a UDP listener and a UDP talker must agree on IP version — sending an IPv4 datagram to an IPv6-only listener does not error, it simply never arrives, which is exactly why the guide’s own example pins both programs to AF_INET6.
Important Questions:
- Why does
server.ccallfork()afteraccept()? So the parent process can immediately go back toaccept()ing new connections while the child process, a full copy of the parent, handles the just-accepted client, letting one server serve many simultaneous clients. - Why doesn’t a UDP server need
listen()oraccept()the way a TCP server does?SOCK_DGRAMsockets are connectionless, so there is no connection to listen for or accept — a UDP server justbind()s a port and callsrecvfrom()directly, which blocks until a packet arrives.
Chapter 7: Slightly Advanced Techniques
Difficulty: Hard · Key topics: blocking, poll(), select(), sendall(), serialization/packing data, broadcast packets, SO_BROADCAST
The guide’s longest and most advanced chapter tackles the problems real network programs hit once a single blocking recv() call is no longer enough. It explains blocking sockets and O_NONBLOCK, then covers both poll() and the older select() for monitoring many sockets at once without busy-waiting, followed by a sendall() helper for handling the case where send() transmits fewer bytes than requested. A substantial serialization section compares three ways to move binary numbers across the wire and argues for packing them into a portable binary format, and the chapter closes with SO_BROADCAST and how to compute and use a subnet’s broadcast address.
Key Points:
accept()and everyrecv()variant block by default;fcntl()withO_NONBLOCKremoves thatpoll()andselect()let one process monitor many sockets for readability/writability at once, avoiding CPU-wasting polling loopsselect()is portable but slow at large connection counts;poll()and event libraries like libevent scale bettersend()is not guaranteed to send every requested byte in one call — asendall()-style loop must handle the remainder- Serializing numbers: text encoding (readable but slow), raw struct copy (fast but non-portable), or packed portable binary (recommended)
SO_BROADCASTmust be explicitly set viasetsockopt()before a socket can send broadcast packets- Broadcast only works over UDP/IPv4; IPv6 uses multicast instead, since it has no broadcast concept
Practice Tip: Write a tiny sendall() wrapper and call it with a buffer of a few megabytes over a local loopback connection — on most systems a single raw send() of that size will visibly return fewer bytes than you asked for, proving the guide’s point instead of just reading it.
Common Mistake: Assuming a single send() call transmitted the entire buffer just because it did not return -1 — send() can legally return fewer bytes than requested, and code that ignores its return value silently drops the remainder of the message.
Important Questions:
- Why does the guide recommend packing numeric data into a portable binary format instead of sending raw struct/int data directly with
send()? Different CPU architectures represent multi-byte numbers, and especially floating-point numbers, differently in memory, so a rawsend()of adoubleorintis not portable between different machine types, while a packing function produces a fixed, agreed-upon byte layout both ends understand identically. - What must a program do before it is allowed to send a UDP broadcast packet? Call
setsockopt()on the socket with theSO_BROADCASToption enabled; without it, an attempt to send to a broadcast address fails.
Chapter 8: Common Questions
Difficulty: Easy · Key topics: Address already in use, SO_REUSEADDR, loopback testing, detecting a closed connection, raw sockets, connect() timeouts
A genuine FAQ chapter built from the questions Beej says he is actually asked, not padding. It covers the classic “Address already in use” bind() error and its SO_REUSEADDR fix, how to test client/server programs on a single machine using the loopback interface without any real network, and how to detect that recv() returning 0 means the remote side has closed its half of the connection. It also points toward raw sockets and ICMP for anyone wanting to write a ping-style utility, and lays out the non-blocking connect()-plus-select() pattern for implementing a custom connection timeout.
Key Points:
- “Address already in use” on
bind()is fixed withsetsockopt()and theSO_REUSEADDRoption - Every machine has a loopback device (localhost / 127.0.0.1), so client/server pairs can be tested with no real network at all
recv()returning exactly0means the remote peer has closed the connection- Raw sockets (
SOCK_RAW) and ICMP are the building blocks for a custom ping-style tool, but are out of this guide’s scope - A custom
connect()timeout requires setting the socket non-blocking first, then usingselect()to wait with a deadline netstatandip routeare the standard tools for inspecting open sockets and the local routing table
Memory Tip: “Zero bytes back means the other side hung up” — recv() returning 0 (not -1) is specifically the signal for a clean remote close, and it is the single most useful fact in this whole FAQ for day-to-day debugging.
Common Mistake: Treating a recv() return value of 0 the same as an error (-1) — they mean different things: 0 means the connection closed cleanly, while -1 means an actual error occurred and errno needs checking.
Important Questions:
- How do you fix the “Address already in use” error when restarting a server on the same port? Call
setsockopt()on the listening socket with theSO_REUSEADDRoption set, before callingbind(), so the kernel allows immediate reuse of a port still in the OS’s TIME_WAIT cleanup state. - Can you develop and test client-server socket programs without an actual network connection? Yes — every machine has a loopback network device (127.0.0.1/localhost), so a client and server can run in two terminal windows on the same computer with no code changes and no real network required.
Appendix: Man Pages Reference
Difficulty: Easy · Key topics: accept(), bind(), connect(), socket(), getaddrinfo(), send()/recv(), select()/poll(), errno, htons() family
A compact, purpose-built reference section — Beej’s own condensed man pages covering 24 of the functions this guide uses, each with a synopsis, short description, return value, and runnable example, deliberately trimmed down from the full system man pages to stay focused on network programming. The guide is explicit that these are simplified and platform-generic; it recommends checking the real man page on your own system for the complete, authoritative version, header requirements, and any platform-specific parameter differences.
Key Points:
- Every entry follows the same shape: Synopsis, Description, Return Value, Example, See Also
- Covers 24 functions, including
accept(),bind(),connect(),getaddrinfo(),send()/recv(),select()/poll(), and thehtons()family - Intentionally incomplete — a trimmed, teaching-focused subset of each function’s real man page
- Each entry includes a short runnable code example, not just a function prototype
- The
errnoentry specifically notes it needs care in multithreaded programs - The guide recommends checking your local
man <function>for the complete, platform-accurate reference
Common Mistake: Copying a function’s argument order or header includes straight from this appendix without checking the local system’s real man page — Beej’s own note in this chapter warns that headers and exact parameters can differ by platform.
Important Questions:
- Why does the guide include its own simplified man pages instead of just pointing readers to
man? These versions are written specifically for network programming and include runnable examples that the real system man pages do not provide, making them easier to learn from even though they are intentionally incomplete. - What does the
errnoentry in this appendix warn about? Thaterrnoneeds care in multithreaded programs, since its thread-safety behavior can differ from the simple global-variable model assumed in the guide’s single-threaded examples.
Read Beej’s Guide to Network Programming (Free)
Beej’s Guide has no official PDF-download landing page separate from the guide itself — the HTML edition below is the guide’s home, and it links directly to the current PDF (multiple paper sizes and colour options) from the same page. There is no paywall, no account and no mailing-list signup; the button opens the author’s own official site, beej.us, and the PDF link on that page is the current, actively-maintained edition.
↓ Read the Guide (HTML)↓ Download PDFHow to Study This Book
Read Chapters 1–3 (About This Guide, What Is a Socket?, and IP Addresses/Structs/Data Munging) in order before touching any code — they build the vocabulary (stream vs. datagram, byte order, struct addrinfo) that every later chapter assumes without re-explaining it. Chapter 4 (Jumping from IPv4 to IPv6) is short and can be skimmed on a first pass; it matters much more once you’re editing IPv4-only code someone else wrote.
Chapter 5 (System Calls or Bust) is the load-bearing chapter of the entire guide. Do not just read it — type each system call’s example into a real file as you go. Chapter 6 (Client-Server Background) is where that investment pays off immediately: server.c and client.c are short enough to fully understand line-by-line, and running them against each other with telnet in a second terminal is the single most useful thing you can do in your first sitting with this guide.
Chapter 7 (Slightly Advanced Techniques) is genuinely harder than everything before it and covers four mostly-independent topics: non-blocking I/O, poll()/select(), handling partial send()s, and serialization. A first read-through of a semester-length networking course can treat poll()/select() as the priority subsection and come back to serialization and broadcast packets once a real assignment needs them.
Chapter 8 (Common Questions) reads like a FAQ because it is one — skim it once early so you recognize the “Address already in use” error and the “recv() returned 0” signal when you actually hit them while debugging your own server, rather than discovering this chapter only after getting stuck.
The Appendix (Man Pages Reference) is not meant to be read start to finish — treat it the way the guide itself intends: a lookup table you jump to while writing code, whenever you forget the exact parameter order or return value of a function like accept() or getaddrinfo().
Because the whole guide is built around runnable C programs rather than abstract description, the single most effective study method is exactly what the guide itself demonstrates: compile and run every example on your own machine as you reach it, using the loopback interface (Chapter 8) so no real network is even required, rather than reading the code as text and trusting that you understand it.
Used In These Programs
This guide is one of the most widely assigned free references for the Network Programming or Sockets Programming component of a Computer Networks course in BS Computer Science programs, and is commonly recommended as self-study for backend, systems, and game-networking roles that work directly with TCP/UDP sockets in C or C++. Browse all socket programming books or all Computer Science books.
Who Should Read This
Beej’s Guide is written for a reader who already knows C — comfortable with pointers, structs and compiling their own programs — but has never written a single line of networked code before. That makes it the right first resource for a BSCS student doing the lab component of a Computer Networks or Systems Programming course, and for any self-taught C programmer who wants to actually build a client or server rather than only read about the OSI model in theory. It teaches no C itself and assumes that foundation is already solid, so it pairs naturally with a fuller networking theory textbook such as Computer Networking: Principles, Protocols and Practice, which covers the protocol theory (routing, congestion control, the full protocol stack) that this guide deliberately treats as optional background in favor of getting a socket open and moving data. It is not the right choice for someone who has never written any C at all, or who is looking for coverage of a specific language’s own networking library instead of the underlying Unix sockets API those libraries are built on.
Applicable Universities
This guide is useful for students at Pakistani universities offering BSCS or BSSE programs with a Computer Networks or Systems Programming course, including Punjab University, Virtual University, COMSATS, FAST, UET, NUST, GIKI, LUMS, and other HEC-recognized institutions, and for any self-taught C programmer preparing for backend, systems, or embedded networking work.
FAQs
Is Beej’s Guide to Network Programming free and legal to download?
Yes. Author Brian “Beej Jorgensen” Hall publishes the complete guide free of charge on his own site, beej.us, in both HTML and PDF form. The guide’s text is licensed CC BY-NC-ND 3.0 (Attribution-NonCommercial-NoDerivatives), and every example C program in the guide is separately released to the public domain, so the code itself carries no restriction at all.
Which edition is this, and is it still current?
This page is built from the guide’s live, continually-revised HTML/PDF edition; the source’s own public revision history reaches version 3.1.5 and includes recent fixes such as a freeaddrinfo() memory-leak fix, a Windows Subsystem for Linux (WSL) note, and IPv6 datagram corrections. Unlike most textbooks, Beej’s Guide has no fixed “edition year” — it is actively maintained and updated by its author rather than republished periodically.
How many chapters or sections does the guide have?
Nine sections in total: About This Guide, What Is a Socket?, IP Addresses/Structs/Data Munging, Jumping from IPv4 to IPv6, System Calls or Bust, Client-Server Background, Slightly Advanced Techniques, Common Questions, and an Appendix reference of 24 condensed man pages for the specific functions the guide uses.
Is it good for complete beginners?
Only if “beginner” means new to networking, not new to C. The guide explicitly assumes the reader already knows C — structs and pointers in particular — and teaches sockets, not the C language itself. A reader who has never written any C should learn the language first from a dedicated C book before starting here.
Does it cover both TCP and UDP, and both IPv4 and IPv6?
Yes, thoroughly. Stream (TCP) and datagram (UDP) sockets are both covered with complete runnable examples (server.c/client.c for TCP, talker.c/listener.c for UDP), and the guide is written IPv6-first using the portable getaddrinfo() API, with a dedicated chapter listing exactly what changes if you are porting older IPv4-only code.
Is Beej’s Guide still relevant in 2026, or has the sockets API changed?
Yes — the Berkeley sockets API the guide teaches (socket(), bind(), connect(), send()/recv(), and friends) is a POSIX standard that has not fundamentally changed in decades, and the guide is actively maintained by its author with ongoing bug fixes and clarifications rather than left static. It remains one of the most recommended free resources for learning sockets programming in C.
Related Books
- Computer Networking: Principles, Protocols and Practice – Bonaventure (the protocol theory — routing, congestion control, the full stack — behind the sockets this guide teaches you to open)
- Operating Systems and Networks – IT Series BSCS (a broader OS-and-networking companion for the same systems-programming coursework)
- Operating Systems: Three Easy Pieces – Arpaci-Dusseau (the OS-level process, file-descriptor, and I/O concepts that socket programming in C sits directly on top of)
Beej’s Guide to Network Programming, by Brian “Beej Jorgensen” Hall, is a free, continually maintained introduction to Unix sockets programming in C — from what a socket actually is through complete TCP and UDP client/server code, IPv6, and the non-blocking I/O and serialization techniques real network programs need. Browse more Computer Science books for the rest of your semester.
Beej’s Guide to Network Programming, by Brian “Beej Jorgensen” Hall. Copyright © 2019 Brian “Beej Jorgensen” Hall, continually revised by the author (source revision history reaches version 3.1.5). Guide text licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 3.0 (CC BY-NC-ND 3.0); all example C source code is separately released to the public domain. Read it free at its official source, https://beej.us/guide/bgnet/
© Copyright Policy
Freebooks.pk is an educational resource for students in Pakistan. Textbooks and other books belong to their respective boards, authors and publishers, and all rights remain with them. If you are the copyright holder of any material on this page and want it changed or removed, please contact us or file a request under our DMCA policy. We review every request and remove reported content promptly.
