Project 03: nvycat
: The Navy Netcat
Table of Contents
Project Preliminaries
Project Learning Goals
The goal of this project are:
- Use client and server sockets dependent on command line arguments
- Implement the functionality of netcat
- Use threading to avoid blocking
Project Grading and Due Date
This project is graded out of 100 points and is due on Mon. 2 May at 2359. Late submissions will not be allowed.
We will apply the following grading rubric to this project
- 60% Complete a
nvcat
that can connect to a server at a domain name and port specified on the command line and reads whatever is written to the socket
- 75% Complete a
nvcat
that can connect to a server at a domain name and port specified on the command line, writes anything provided from stdin to the socket, and can reads whatever is written to the socket (not in a loop – one shot). - 82% Complete a
nvcat
that can connect to a server at a domain name and port specified on the command line, writes anything provided from stdin to the socket, and can reads whatever is written to the socket, in a loop, synchronously (one read for every write). - 92% Complete a
nvcat
that can connect to a server at a domain name and port specified on the command line, writes anything provided from stdin to the socket, and can reads whatever is written to the socket, in a loop, asynchronously by using threading to allow for reading and writing at the same time. - 100% Complete a
nvcat
that can connect to a server at a domain name and port specified on the command line, or act as server binding to a particular port and perform asynchronous reading and writing from the stdin/stdout to the socket.
Additional Requirements:
- You must provide a Makefile to compile your program
- You must ensure that there are no memory leaks and no deadlock possible
- You must provide a
README
file for your program describing tasks completed and processes used. This is also the place to provide additional details to your grader. - You must provide a
man.txt
file describing the operations of your command line tool.
Project Setup:
- Run the following command in your terminal
~aviv/bin/ic221-up
- Then change into the following directory
cd ic221/proj/03
- You will find all the material you need to complete this lab in that directory.
- During the course of this lab, we will refer to the
ic221/proj/03
as the project directory
Project Submission
To submit this lab you will place all relevant content into your lab directory:
ic221/proj/02
Then issue the submission script
~aviv/bin/ic221-submit
Select the option for proj/03
, and confirm. If you see SUCCESS
at the end. You may submit multiple times up until the submission
deadline. Only your final submission will be considered for
grading.
Project Description
In this project, you will implement your own version of the netcat
utility called nvycat
(the Navy Network Cat). netcat
is one of
the most useful tools in network programming, and, in fact, you
should use netcat
as a testing tool for your project.
When complete, your nvycat
utiltity will be able to do the
following things:
- Connect to a server at a given port sepcified on the command line
- Read from stdin and write any data to the socket, to be sent to the server
- Read from the socket (from the server) and write that data to stdout
- Perform reading/writing asynchronously so that it will not
block on
read()
either on the socket or stdin prior to writing data to the screen. - Act as a server if the
-l
argument is given.
Here's a demo of a working version of the nvycat
acting in different ways.
First, nvycat
can act as a simple client interacting with remote
servers on different ports. (Note the GET ...
is typed by me and
sent to the server, the response is printed to stdout.)
aviv@saddleback: sol ./nvycat yog.cs.usna.edu 80 GET /~aviv/index.html <html> <h1> You did it! </h1> </html> aviv@saddleback: sol $ ./nvycat yog.cs.usna.edu 80 GET /~aviv/saturn.txt _.oo. _.u[[/;:,. .odMMMMMM' .o888UU[[[/;:-. .o@P^ MMM^ oN88888UU[[[/;::-. dP^ dNMMNN888UU[[[/;:--. .o@P^ ,MMMMMMN888UU[[/;::-. o@^ NNMMMNN888UU[[[/~.o@P^ 888888888UU[[[/o@^-.. oI8888UU[[[/o@P^:--.. .@^ YUU[[[/o@^;::---.. oMP ^/o@P^;:::---.. .dMMM .o@^ ^;::---... dMMMMMMM@^` `^^^^ YMMMUP^ ^^ aviv@saddleback: sol $ ./nvycat saddleback.academy.usna.edu 6666 MMMMMMMMMMMMMMMMMMMMM. MMMMMMMMMMMMMMMMMMMMM `MMMMMMMMMMMMMMMMMMMM M\ /M MMMMMMMMMMMMMMMMMMMM' `MMMMMMMMMMMMMMMMMMM MMMMMM MMMMMMMMMMMMMMMMMMM' MMMMMMMMMMMMMMMMMMM-_______MMMMMMMM_______-MMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM `MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM' `MMMMMMMMMMMMMMMMMM' `MMMMMMMMMM' MMMMMM MMMM MM
Second, nvycat
can act as a server, and either plain ol' netcat
or a nvycat
can connect to it, allowing for chatting. Note, that
this communication between two machines.
On the server, it is listening on port 2233, and on the client, it
connected and wrote the saturn.txt
to the socket, appearing on the
server.
aviv@mich302csd02u: sol $ ./nvycat -l 2233 _.oo. _.u[[/;:,. .odMMMMMM' .o888UU[[[/;:-. .o@P^ MMM^ oN88888UU[[[/;::-. dP^ dNMMNN888UU[[[/;:--. .o@P^ ,MMMMMMN888UU[[/;::-. o@^ NNMMMNN888UU[[[/~.o@P^ 888888888UU[[[/o@^-.. oI8888UU[[[/o@P^:--.. .@^ YUU[[[/o@^;::---.. oMP ^/o@P^;:::---.. .dMMM .o@^ ^;::---... dMMMMMMM@^` `^^^^ YMMMUP^ ^^
./nvycat mich302csd02u.academy.usna.edu 2233 < saturn.txt
You can also have two way communications:
aviv@mich302csd02u: sol $ ./nvycat -l 3322 I'm the client! Nice to meet you, I'm the server The client or server enters Ctrl-D to end the session
./nvycat mich302csd02u.academy.usna.edu 3322 I'm the client! Nice to meet you, I'm the server The client or server enters Ctrl-D to end the session
Binding to remotely accessible address for the server
One thing that you'll need to do is make your server socket bind to
address that is remotely accessible. This means, you'll need to set
up the sin_addr
field directly rather than resolve a
hostname. Fortunately, if you set this to 0, e.g., via
INADDR_ANY
, that is all you need.
Dealing with errors
There are a ton(!) of systems calls in this, all of which could
fail. You should check for all system call failures and domain
resolution errors and print appropriate messages using
perror()
and written to stderr
. Below is an incomplete example:
aviv@mich302csd02u: sol $ ./nvycat ERROR: require arguments aviv@mich302csd02u: sol $ ./nvycat a ERROR: require arguments aviv@mich302csd02u: sol $ ./nvycat a b ERROR: invalid port aviv@mich302csd02u: sol $ ./nvycat a 10 getaddrinfo: Name or service not known aviv@mich302csd02u: sol $ ./nvycat -l 10 bind: Permission denied aviv@mich302csd02u: sol $ ./nvycat mich302csd01u 10 connect: Connection refused
More Tips
- Use
netcat
for testing. It's super useful. - Don't try and do everything all at once, for example, start with just doing a simple client that doesn't go back and forth, then add that functionality later.
- Keep it simple when it comes to threading. Only place things within child-threads that really need to be there.
- If the main-thread dies, all threads die. Don't forget to join!