Graphics Programs Reference
In-Depth Information
fatal("in socket");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
fatal("setting socket option SO_REUSEADDR");
So far, the program sets up a socket using the
socket()
function. We want
a TCP/IP socket, so the protocol family is
PF_INET
for IPv4 and the socket type
is
SOCK_STREAM
for a stream socket. The final protocol argument is
0
, since there
is only one protocol in the
PF_INET
protocol family. This function returns a
socket file descriptor which is stored in
sockfd
.
The
setsockopt()
function is simply used to set socket options. This func-
tion call sets the
SO_REUSEADDR
socket option to
true
, which will allow it to reuse
a given address for binding. Without this option set, when the program tries
to bind to a given port, it will fail if that port is already in use. If a socket isn't
closed properly, it may appear to be in use, so this option lets a socket bind to
a port (and take over control of it), even if it seems to be in use.
The first argument to this function is the socket (referenced by a file
descriptor), the second specifies the level of the option, and the third specifies
the option itself. Since
SO_REUSEADDR
is a socket-level option, the level is set to
SOL_SOCKET
. There are many different socket options defined in /usr/include/
asm/socket.h. The final two arguments are a pointer to the data that the
option should be set to and the length of that data. A pointer to data and the
length of that data are two arguments that are often used with socket func-
tions. This allows the functions to handle all sorts of data, from single bytes
to large data structures. The
SO_REUSEADDR
options uses a 32-bit integer for its
value, so to set this option to
true
, the final two arguments must be a pointer
to the integer value of
1
and the size of an integer (which is 4 bytes).
host_addr.sin_family = AF_INET; // Host byte order
host_addr.sin_port = htons(PORT); // Short, network byte order
host_addr.sin_addr.s_addr = 0; // Automatically fill with my IP.
memset(&(host_addr.sin_zero), '\0', 8); // Zero the rest of the struct.
if (bind(sockfd, (struct sockaddr *)&host_addr, sizeof(struct sockaddr)) == -1)
fatal("binding to socket");
if (listen(sockfd, 5) == -1)
fatal("listening on socket");
These next few lines set up the
host_addr
structure for use in the bind call.
The address family is
AF_INET
, since we are using IPv4 and the
sockaddr_in
structure. The port is set to
PORT
, which is defined as
7890
. This short integer
value must be converted into network byte order, so the
htons()
function is
used. The address is set to
0
, which means it will automatically be filled with
the host's current IP address. Since the value
0
is the same regardless of byte
order, no conversion is necessary.
The
bind()
call passes the socket file descriptor, the address structure,
and the length of the address structure. This call will bind the socket to the
current IP address on port 7890.