Beej’s Guide to Network Programming Using Internet Sockets 11
4. System Calls or Bust
This is the section where we get into the system calls that allow you to access the network
functionality of a Unix box. When you call one of these functions, the kernel takes over and does
all the work for you automagically.
The place most people get stuck around here is what order to call these things in. In that, the
man pages are no use, as you’ve probably discovered. Well, to help with that dreadful situation,
I’ve tried to lay out the system calls in the following sections in exactly (approximately) the same
order that you’ll need to call them in your programs.
That, coupled with a few pieces of sample code here and there, some milk and cookies (which
I fear you will have to supply yourself), and some raw guts and courage, and you’ll be beaming
data around the Internet like the Son of Jon Postel!
4.1. socket()–Get the File Descriptor!
I guess I can put it off no longer–I have to talk about the socket() system call. Here’s the
breakdown:
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
But what are these arguments? First, domain should be set to “PF_INET”. Next, the type
argument tells the kernel what kind of socket this is: SOCK_STREAM or SOCK_DGRAM. Finally, just
set protocol to “0” to have socket() choose the correct protocol based on the type. (Notes:
there are many more domains than I’ve listed. There are many more types than I’ve listed. See
the socket() man page. Also, there’s a “better” way to get the protocol, but specifying 0 works
in 99.9% of all cases. See the getprotobyname() man page if you’re curious.)
socket() simply returns to you a socket descriptor that you can use in later system calls, or
-1 on error. The global variable errno is set to the error’s value (see the perror() man page.)
(This PF_INET thing is a close relative of the AF_INET that you used when initializing the
sin_family field in your struct sockaddr_in. In fact, they’re so closely related that they
actually have the same value, and many programmers will call socket() and pass AF_INET as
the first argument instead of PF_INET. Now, get some milk and cookies, because it’s times for
a story. Once upon a time, a long time ago, it was thought that maybe a address family (what
the “AF” in “AF_INET” stands for) might support several protocols that were referred to by their
protocol family (what the “PF” in “PF_INET” stands for). That didn’t happen. And they all lived
happily ever after, The End. So the most correct thing to do is to use AF_INET in your struct
sockaddr_in and PF_INET in your call to socket().)
Fine, fine, fine, but what good is this socket? The answer is that it’s really no good by itself,
and you need to read on and make more system calls for it to make any sense.
4.2. bind()–What port am I on?
Once you have a socket, you might have to associate that socket with a port on your local
machine. (This is commonly done if you’re going to listen() for incoming connections on a
specific port–MUDs do this when they tell you to “telnet to x.y.z port 6969”.) The port number is