Description

These are the
basic structures for all syscalls and functions that deal with internet
addresses. Often you'll use getaddinfo() to fill these
structures out, and then will read them when you have to.

In memory, the struct sockaddr_in and struct
sockaddr_in6 share the same beginning structure as struct sockaddr, and you can freely
cast the pointer of one type to the other without any harm, except the
possible end of the universe.

Just kidding on that end-of-the-universe thing...if the universe does
end when you cast a struct sockaddr_in* to a struct
sockaddr*, I promise you it's pure coincidence and you shouldn't
even worry about it.

So, with that in mind, remember that whenever a function says it
takes a struct sockaddr* you can cast your struct
sockaddr_in*, struct sockaddr_in6*, or struct
sockadd_storage* to that type with ease and safety.

struct sockaddr_in is the structure used with IPv4
addresses (e.g. "192.0.2.10"). It holds an address family
(AF_INET), a port in sin_port, and an IPv4
address in sin_addr.

There's also this sin_zero field in struct
sockaddr_in which some people claim must be set to zero. Other
people don't claim anything about it (the Linux documentation doesn't
even mention it at all), and setting it to zero doesn't seem to be
actually necessary. So, if you feel like it, set it to zero using
memset().

Now, that struct in_addr is a weird beast on different
systems. Sometimes it's a crazy union with all kinds of
#defines and other nonsense. But what you should do is only
use the s_addr field in this structure, because many systems
only implement that one.

struct sockadd_in6 and struct in6_addr are
very similar, except they're used for IPv6.

struct sockaddr_storage is a struct you can pass to
accept() or recvfrom() when you're trying to
write IP version-agnostic code and you don't know if the new address is
going to be IPv4 or IPv6. The struct sockaddr_storage
structure is large enough to hold both types, unlike the original small
struct sockaddr.