Part 2 Due: Wednesday 17 before 11:59pm
(push to your Lab02 git repo with Part2 tag by then)
Part 3 Due: Wednesday 17 before 11:59pm
(required for taken-NW groups, optional for other groups)
(push to your Lab02 git repo with Part3 tag by then)
This lab should be done with your lab 2 partner
In this lab you will implement at least 2 different versions of the client and server.
The Part 1 solution is due in one week.
The Part 2 solution is due in two weeks.
The Part 3 solution is due in two weeks.
To run talk on our system:
# to initiate a talk session with someone on another machine: talk username machinename # the other person will respond with: talk you yourmachine # let's say Jeff from cumin does this talk newhall lime # Tia from lime would respond with this to start the chat session talk knerr cuminAGAIN: you are NOT implementing the talk protocol, nor its exact functionality in this assignment.
mkdir cs87 mkdir cs87/labs cd cs87/labs
git clone [your_Lab02_URL]Then cd into your Lab02-you-partner subdirectory.
Makefile client.c cs87talk.c cs87talk.h server.cIf this didn't work, or for more detailed instructions on git see: the Using Git page (follow the instructions for repos on Swarthmore's GitHub Enterprise server).
# on some machine start the server: ./cs87_server # connect to the server on another machine # list its IP address and your chat session name # as command line options: ./cs87_client 22.214.171.124 tiaYou can use the CS department machine specs page to find other machines to ssh into and run clients or servers.
For this lab you will implement three different high-level message protocols as part of the cs87talk protocol. The three are:
Each part of the protocol is begun by one party sending to the other party 1 byte message tag. The tag value is used to indicate which of the three messaging protocols the client and server should run (the expected send-recv sequence between the client and server for the interaction type is indicated by the tag).
client server ====== ====== 1. send HELLO_MSG tag -------------> recv 1 byte tag 2. send len -----------------------> recv 1 byte len 3. send name ----------------------> recv a len bytes name string 4. recv 1 byte tag <---------------- send 1 byte reply tag (HELLO_OK or HELLO_ERROR)The client sends 3 values to the server in this order: the HELLO_MSG tag as a 1 byte value; a 1 byte len value, which is the number of bytes in the name string; and a len bytes message containing the name string (passed as a command line argument to the client program). The client then receives the 1 byte tag response from the server, indicating if the server is letting it join the talk session.
The server will terminate the connection after it replies HELLO_ERROR. If it replies HELLO_OK, it will update state about this connection, and create a message buffer for this client with the client's name string as a prefix. All messages set by this client will be prefixed by the string "name:" to mark that this message was "said" by this client.
initiator other end ========= ========= 1. send MSG_DATA ------------------> recv 1 byte tag value 2. send len -----------------------> recv 1 byte len value 3. send data ----------------------> recv len byte messageIf the server is the "other end" it always stored the received message in a string with the a "name:" prefix (obtained from the HELLO protocol) to identify the sender.
If the client is the "other end" it just receives the message of len bytes and creates a string from the len byte message (null terminate '\0' before printing out); the client side doesn't add a prefix to received messages.
client server ====== ====== 1. send QUIT -----------------------> recv 1 byte tag value
After sending QUIT, the client should close its end of the socket and exit.
The server then cleans up any state associated with this connect, including closing its end of the socket.
After receiving a QUIT, the server process should not exit. For Part 1, it is ready to accept a new connection. For Part 2, this client has just left the group chat.
The behavior should be:
./cs87_client 126.96.36.199 tia
tsize_t tag; tag = HELLO_OK; ret = send(socket, &tag, sizeof(tsize_t), MSG_NOSIGNAL);
This means that a client message length plus the name prefix length longer than BUFMAX will result in the client message being truncated to fit in this buffer. If the prefix is "tia:" then there are 4 fewer characters for a message. If the prefix is "kevin:" then there are 6 fewer. You should also leave the last bucket in this buffer for storing a null terminating character for the string '\0'. '\0' shouldn't be passed in the message.
NOTE: with the exception of 1 byte messages, receive should be called in a loop until all the bytes of the message have been received. You can specify the next point to receive in a buffer by passing recv the address of the bucket:
ret = recv(sock, &(buf[i]), amt_left, 0);
Also, Steven's Unix Network Programming (2nd Edition Vol. 1). Chapters 3 and 4 are very helpful. A copy of this book is in the CS Lab.
struct linger linger_val; linger_val.l_onoff = 0; linger_val.l_linger = 0; setsockopt(sock_fd, , SO_LINGER, (void *)linger_val, (socklen_t) (sizeof(struct linger));
$ /sbin/ifconfig # in the eth0 entry its "inet addr:"
printf("hello there"); fflush(stdout); // force all buffered printf output to stdout
You are not required to do this, but
if you want to try to implement a solution with nicer looking output,
you can try using the ncurses library to split the terminal window and
direct stdin to one half and stdout and stderror to the other half (this
is not trivial to do). You could also try something easier and print out
stdout output in a different color if it is coming from the prompt printing
thread vs. from the thread that receives and prints out messages
from other clients forwarded from the server. Here is some
information about ncurses: Cool C libraries.
This part is required for the lab2 partners who have taken a Networking course, and optional for the groups who have not.
For this part, you are going to add a new protocol to your Part2 solution. When a new client wants to connect to a chat session (via the HELLO protocol), the current set of clients will decide if they are going to let the new client join the chat session or not. If the current clients in the chat choose NO, then the server will reply with HELLO_ERROR and not let the new client join. If the current clients choose yes, then the server will reply with HELLO_OK and the new client can join in the group chat.
This protocol should be VERY simple. This is just the agreed message exchange between the server and clients already participating in a chat. It should be similar to one of the existing protocls like HELLO or MSG. If it starts to get longer than about 2x any of the current ones, step back and simplify.
Group's particular voting algorithms can differ, but the messaging protocol used by client and server processes should be the same; your group may choose any algorithm for tallying a result, but your group's client should know how to interpret a voting message request from another group's server, and your server should be able to have a voting interaction that includes another group's client program.
Publish your agreed upon protocol on piazza or the wiki (you can create a new page for the Lab2 Voting Protocol off the top-level class wiki page. Use the chain looking link to do this).
Some Advice: in designing the protocol try very hard to separate out the protocol design from how it will be implemented. For example, worrying about race conditions or deadlock or clients exiting are all implementation issues and should not be part of the protocol (other than ensuring that your msgs send-recvs in the protocol are not a deadlock). Focus solely on the message exchange between clients and servers to initiate a voting session and to collect votes. Similarly, the particular voting algorithm is not part of the protocol. You do not need to agree on a voting algorithm; one group could choose a majority algorithm of the client's votes, another could choose random, anther ...
You do not need to support any number of simultaneous voting of letting
in new clients. For example, if a second new client tries to join
the chat during the voting decision for a current new client, it is fine
to serialize the voting process: first complete the voting decision about
the first new client, then start the voting process on the second new client.
From one of your local repos (in your ~you/cs87/labs/Lab02-partner1-partner2 subdirectory)
git add *.c *.h git commit git pushAlso TAG your commit: because you are going to implement your Part 2 (and Part 3) in the same repo as your Part 1, you should add a git tag to your submitted solution to a particular part.
To do this:
# list all current tags associated with a repo git tag -l # create a new tag named Part1 with a tag message (optional) # and share a tag: push the tag to the origin to share it: git tag -a Part1 -m "soln to Part1" git push origin Part1 # checking out a specific tagged version of the code # (checkout Part1 version of code into a local repo named my_part1)" git checkout -b my_part1 Part1 # to list other data along with the commit for a specific tag # (this will show the commit number, date and who created the tag): git show Part1You must name it exactly Part1 (and Part2 for part2) otherwise your professor will be very sad.
If you have git problems, take a look at the "Troubleshooting" section of the Using git page.