Table of Contents
In subnets, the network portion of the IP address is described by something called the netmask, which you bitwise-AND with the IP address to get the network number out of it. The netmask usually looks something like 255.255.255.0. (E.g. with that netmask, if your IP is 192.0.2.12, then your network is 192.0.2.12 AND 255.255.255.0 which gives 192.0.2.0.)
Beej analogy for ports: Think of the IP address as the street address of a hotel, and the port number as the room number. That’s a decent analogy
SOCK_STREAM
uses TCP. SOCK_DGRAM
uses UDP (User Datagram Protocol)
On Byte order:
htons()
: host to network shorthtonl()
: host to network longntohs()
: network to host shortntohl()
: network to host longinet_pton()
Converts an OP address in numbers and dots notation into either a struct in_addr
or a struct in6_addr
depending on whether you specify AF_INET
or AF_INET6
.
There is also the reverse function: inet_ntop()
💡 Note: “pton” stands for “presentation to network”—you can call it “printable to network” if that’s easier to remember.
System Calls or Bust:
getaddrinfo()
: It helps set up the structs you need later on like struct addrinfo
. As input parameters it has the host name or IP address to connect, the service (port number or service name) and it gives you a pointer to a linked-list, res, of results.socket()
: It used to be people would hardcode these values, and you can absolutely still do that. (domain is PF_INET or PF_INET6, type is SOCK_STREAM or SOCK_DGRAM, and protocol can be set to 0 to choose the proper protocol for the given type. Or you can call getprotobyname() to look up the protocol you want, “tcp” or “udp”.). It returns to you a socket descriptor that you can use in later system calls.
bind()
: Once you have a socket, you might have to associate that socket with a port on your local machine.💡 Note: The port number is used by the kernel to match an incoming packet to a certain process’s socket descriptor.
💡 Note: All ports below 1024 are RESERVED (unless you’re the superuser)! You can have any port number above that, right up to 65535 (provided they aren’t already being used by another program).
connect()
: Connects to a remote host.
listen()
: When you want to wait for incoming connections and handle them in some way. The process is two step: first you listen()
, then you accept()
(see below).
accept()
: What’s going to happen is this: someone far far away will try to connect() to your machine on a port that you are listen()ing on. Their connection will be queued up waiting to be accept()ed. You call accept() and you tell it to get the pending connection. It’ll return to you a brand new socket file descriptor to use for this single connection!
send()
and recv()
: These two functions are for communicating over stream sockets or connected datagram sockets.
💡Note: If you want to use regular unconnected datagram sockets, you’ll need to see the section on
sendto()
andrecvfrom()
close()
and shutdown()
: You’ve been send()ing and recv()ing data all day long, and you’ve had it. You’re ready to close the connection on your socket descriptor. This is easy. You can just use the regular Unix file descriptor close() function. Just in case you want a little more control over how the socket closes, you can use the shutdown() function. It allows you to cut off communication in a certain direction, or both ways (just like close() does).
getpeername()
: This function will tell you who is at the other end of a connected stream socket.
gethostname()
: It returns the name of the computer that your program is running on. The name can then be used by gethostbyname()
, below, to determine the IP address of your local machine.
There are a lot of functions that block, like accept()
and recv()
. If you down want a socket to be blocking you have to make a call to fcntl()
. By setting a socket to non-blocking, you can effectively “poll” the socket for information.
poll()
: In a nutshell, we’re going to ask the operating system to do all the dirty work for us, and just let us know when some data is ready to read on which sockets. In the meantime, our process can go to sleep, saving system resources.
select()
gives you the power to monitor several sockets at the same time. It’ll tell you which ones are ready for reading, which are ready for writing, and which sockets have raised exceptions if you really want to know that.
Serialization options:
sprintf()
, then send the text. The receiver will parse the text back into a number using a function like strtol()
.send()
.Data Encapsulation: In the simplest case, it means you’ll stick a header on there with either some identifying information or a packet length, or both.
Broadcasting: Send data to multiple hosts at the same time. Broadcasting can be done with UDP (only UDP, not TCP) and standard IPv4.
MTU (Maximum Transmission Unit)-: Maximum size the physical medium can handle. On the local machine, you’re using the loopback device which can handle 8K or more, no problem. But on Ethernet, which can only handle 1500 bytes with a header.
Firewalls prevent people outside the firewall from connecting to machines inside the firewall.