Networking in C · intermediate · ~8 min
Recognize the `errno` values you will see most often, and understand what each one means.
When a socket call fails, it returns -1 and sets the global variable errno. The value of errno tells you why it failed. Knowing the common values lets you decide whether to retry, give up, or report the problem.
| errno | Where you see it | What it means |
|---|---|---|
EADDRINUSE |
bind |
The port is already taken. Use SO_REUSEADDR or pick another port. |
EACCES |
bind |
You tried to use a privileged port (below 1024) without root. |
ECONNREFUSED |
connect |
Nothing is listening on that address and port. |
ETIMEDOUT |
connect |
The connection request (SYN) got no answer. |
ECONNRESET |
recv / send |
The peer crashed or closed abruptly (it sent an RST instead of a clean FIN). |
EPIPE |
send |
The peer already closed. SIGPIPE was raised (unless you used MSG_NOSIGNAL). |
EAGAIN |
non-blocking sockets | The call would block right now. Try again later. |
EINTR |
any syscall | A signal interrupted the call. Retry it, or set SA_RESTART. |
ENETUNREACH |
connect |
No route to the destination exists. You will see this in --network=none sandboxes. |
A quick note on the terms above:
SIGPIPE is a signal the system sends when you write to a closed connection. By default it kills your program.Wrap every socket call in an error check:
if (rc < 0) {
switch (errno) {
/* handle each case */
}
}
The key idea is that your loop must know the difference between two kinds of failure:
EINTR, EAGAIN) — try the call again.ssize_t n;
do { n = recv(fd, buf, cap, 0); } while (n < 0 && errno == EINTR);
if (n < 0) perror("recv");
else if (n == 0) printf("peer closed\n");
else buf[n] = 0;
-1 from a syscall as fatal. EINTR and EAGAIN are retryable — the call simply needs to run again.EADDRINUSE, ECONNREFUSED, ECONNRESET, EPIPE, EAGAIN, EINTR.EINTR and EAGAIN.