Sockets are a fundamental abstraction for many types of computer communication- both inside a single machine and over networks. They are the basic primitives used to connect machines together, and they are used to implement all kinds of networked communication. Despite this, they are surprisingly simple to use, as they encapsulate and hide virtually all of the technical details need to accomplish such communication, and are accessed (like many other things in Linux) just like you were reading or writing a local file.
In this studio, you will:
socket()
, bind()
, and listen()
accept()
and connect()
Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete.
As you work through these exercises, please record your answers, and when finished email your results to dferry_submit@slu.edu with the phrase Sockets in the subject line.
Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.
man 2 bind
under the section
labeled EXAMPLE. Feel free to copy this code, but be sure to cite it.
Your server should perform the following actions:
socket()
. To
create a local connection use the domain AF_LOCAL
(or equivalently AF_UNIX
), the connection type
SOCK_STREAM
, and protocol zero.
bind()
system call. This associates your socket from step one with a machine-visible
address. In the case of AF_LOCAL
, this address is a path in the
file system. Directions on how to specify a local address in this way can be
found at man 7 unix
.
listen()
system
call. Sockets only allow one process to connect at a time, so the second parameter
determines how many connection requests can wait in line before they are rejected.
accept()
system call to accept a connection
over the socket interface. If no connection is immediately available then this
system call will, by default, cause your program block until another program
attempts to connect.
accept()
the
connection has been established. You may read and write data over the channel
with the lower level read()
and write()
system
calls, or you can instantiate a stream interface with the fdopen
function. When doing so, be sure to use the socket descriptor returned by
the call to accept()
, not the one created by the initial call
to socket()
. Have your server read from the socket and print
what it gets to the console.
unlink()
in order to destroy
the socket and connection before the program returns.
Note: Many things can go wrong with socket-based communication.
As usual, you should always check function return codes to detect errors. Recall
that most functions allow you to print a descriptive error statement with a
line of code such as:
perror("Error calling bind()")
.
socket()
system call.
connect()
system call. This
requires using the same socket address struct as the call to bind()
.
At this point, barring any errors, your communcations channel is ready to be used. Send some messages to the server program and print them to standard output in order to validate the functionality. Copy and paste the server output as the answer to this exercise. Note that a call to read an empty socket will block until data is available.
accept()
, but not to
listen()
or bind()
.
Print a message each time a new connection is established and run your client program
several times with the same server to validate this behavior. Copy and paste
the server output as the answer to this exercise.
strncmp
to test for string equality. The similar function
strcmp
is unsafe.
Copy and paste terminal output demonstrating this functionality