Worth 100 points. There might be slight changes to this file in the next 7 days as inevitably bugs and typos are reported. The final version will be version 1.0. (Look, google only releases their betas and you use their softwares daily. Moreover, if you're a software developer, you'll notice that users don't really know precisely what their software requirements are.)
By implementing the program specified in this assignment, you will get familiar with the Unix network programming API (specifically, the Berkeley socket API). The assignment is to be done in groups of size at most 2. You are responsible for finding your partner (if you need one), for finishing off the assignment in case your partner drops the class or backs out from completing the assignment for whatever reason. Please carefully read the sample codes I've given, and re-use some of the subroutines and code structures from the examples. Doing so is not absolutely required, but it will likely save you a lot of time.
The program is to be written in C under a Unix platform such as Linux, SunOS, Solaris, Mac OS X, or FreeBSD. Please make sure that:
Makefile
I provided (in the sample codes) as a template, so
that we can compile your program under these two platforms without
change. All you have to do is to re-define the PROGS
variable
appropriately.The program to be written is called chatty
(or your favourite name), whose features are described below.
Note that there is only one program to be
written. Many
students in the past tried to write a 'client'
and a 'server', for unknown
reasons!
chatty
takes as arguments a TCP port and a UDP port
on which it will listen to
incoming TCP connection requests and incoming udp packets,
respectively:
chatty <tcp-port> <udp-port>
chatty
must handle improper inputs graciously, i.e.
some kind of error report and
usage information should be printed if the user does not type the
correct input parameters, or if the ports cannot be bound, etc.chatty
operates somewhat like a Unix shell. It keeps
taking user's commands,
at the same time watches incoming connection requests and data packets.
When appropriate chatty
prints out diagnostic information to stdout
and then goes back
to the "prompt mode" to accept user's inputs.
Below is a description of
all commands chatty
is supposed to handle, along with the description of associated
actions:
info
: print out its IP address, host name, TCP
(listening) port, UDP port, and process ID. The output of the info
command looks like this:IP address | hostname | udp port | tcp port | PID
------------------------------------------------------------------
192.168.0.3 | funny.cse.buffalo.edu | 4892 | 43444 | 513105
connect <destination> <tcp-port>
:
try to establish a tcp connection to <destination>
at port <tcp-port>
, where <destination>
is either an IP-address or a host name. For example,
connect 192.168.0.3 99999and
connect timberlake.cse.buffalo.edu 99999are both valid inputs. The two functions
getaddrinfo()
and getnameinfo()
will be useful here. Do not use gethostbyname()
and gethostbyaddr()
because they are deprecated by getaddrinfo()
,
and they are not thread-safe.
Both sides of the connection then report that
the connection is indeed established or not (i.e. been denied, or
IP/port does not exist). The error messages have to be informative on
what happened. Note that every TCP connection has to be kept alive
until either one end quits or closes the connection. Note also that, if
you use getaddrinfo()
correctly then the following must
also work
connect timberlake 99999
show
:
show all existing tcp connections in the following format:
cID | IP | hostname | local port | remote portThe
------------------------------------------------------------------
1 | 192.168.0.1 | abc.cse.buffalo.edu | 1234 | 1235
2 | 192.168.0.2 | def.cse.buffalo.edu | 1453 | 98234
3 | 192.168.0.3 | ghi.cse.buffalo.edu | 1233 | 09823
4 | 192.168.0.4 | xyz.cse.buffalo.edu | 1235 | 0823
cID
(or connection ID) can be any index to uniquely identify a connection.
It is probably convenient if you just use the index to some array in
which you store information about the connections. send <conn-id> <message>
:
send <message>
to the TCP connection whose id is <conn-id>
.
Here, <message>
is the string of all characters
that follow <conn-id>
, except for the first blank
space. For
example, the command might look like thissend 3 Oh! This assignment is a piece of cake.
The side which sent a message reports on what it has just sent; for example,
TCP message: "Oh! This assignment is a piece of cake"
to conn. #: 3
The receiving side reports on what it had just received, in the following format
received mesg: "Oh! This assignment is a piece of cake"
protocol: TCP, connection number 5
sender's PID: 12345
sendto
<destination> <udp-port>
<message>
: send <message>
in a UDP datagram to <destination>
at <udp-port>
. Again, <destination>
can either be an IP address or a host name.The side which sent a message reports on what it has just sent; for example,
UDP message: "Oh! This assignment is a piece of cake"
to destination: 192.168.1.104, which is timberlake.cse.buffalo.edu
port: 5665
The receiver reports
received mesg: "Oh! This assignment is a piece of cake"
protocol: UDP
sender: (192.168.1.04, timberlake.cse.buffalo.edu) --- port: 4544
sender's PID: 12345
disconnect <conn-id>
:
disconnect the tcp connection whose id is <conn-id>
.connection number 5 was closed by peer
The side which received the disconnect
command from
the user
reports something like:
connection number 3 is closed
quit
: quit the current chatty
peer.
The peers which are connected to this quitting peer report that the
corresponding connections are closed, as if a disconnect
has just been issued from the quitting peer. unknown
command
"Byte # | Content |
---|---|
0 to 3 | Payload length (PL), 4-byte integer in big-endian. Equal to 4 + message length |
4 to 7 | Sender's process ID (PID), 4-byte integer in big-endian format. |
8 to [PL+3] | The message it self, e.g., "Oh! this is a piece of cake" |
Byte # | Content |
---|---|
0 to 3 | Sender's process ID (PID), 4-byte integer in big-endian format. |
4 to the end | The message it self, e.g., "Oh! this is a piece of cake" |
chatty
must
be able to handle up to 5
TCP connections at the same time. If the maximum is reached, chatty
will either display an error message (if the extra connection request
comes from the command line), or deny the connection establishment
request (if the extra request comes from another process -- by "deny" I
mean simply
"accept()
" and then "close()
" the socket
right
away, which makes your life simpler. select()
for I/O multiplexing of TCP sockets, UDP socket, and stdin
. Do not use multi-processing (with fork()
) or multi-threading.chatty
. We follow exactly the same protocol as
specified
above. When debugging, note the followings