Lab 7: Client/Server
In this lab you'll extend your database program to be accessible over a network.
When you're done with this lab you will have done the following things:
- Get your computers talking to each other.
- Morph your database program into a database server
- Create a client to interact with the database over a network
- Test the limits of your database system
Before proceeding to the following lab instruction, please complete the prelab here if you haven't.
Create a Database Server
Inspect
server.c
. Much of the code in here is similar to your previous implementation oflocal.c
, but some is different.The First function to implement is
runServer
. This function sets up the server socket and listens for incoming connections (handling one at a time). Things to implement (Look inrunServer()
):- Use
bind
to bind the socket to an address - Use
listen
to make the socket listen for incoming requests - Inside the loop, repeatedly handle clients:
- accept the connection on a client socket
- call
handleRemoteInput
to interact with the client - close the client socket using
shutdown
andclose
- Be sure to check your function calls for error return values!
- More details in the
TODO
comments.
- Use
Test out the server using
nc
. Run the server (./server
on your Linux) and leave it running. Open another Linux window (so now you have two terminals). In the new window, connect to your server on the same computer using:nc 127.0.0.1 20000
127.0.0.1 means "this computer". What does the server do? Is it what you expected?
Once you've got
nc
to cause your server to do something, try connecting to your server from your partner's laptop.Implement
handleRemoteInput
to 1) receive input from the client instead of fromstdin
and 2) to send messages to the client instead of printing to stdout. Some hints:- In this client-server communication, we will use the following conventions:
- To communicate a string, the sender does not send the terminating
\0
. It is the job of the receiving party to appropriately null-terminate the data. (Remember thatrecv
returns the number of bytes received.) - If a string was read in with
fgets
onstdin
(and thus the string has a newline\n
at the end), again it is the job of the receiving party to strip off this newline, if necessary.
- To communicate a string, the sender does not send the terminating
sprintf()
can be used to print a string into a buffer that you can send to a client. Use it much likeprintf
, but you print into a char buffer instead of to the screen. For example:char buf[512]; sprintf(buf, "The number is %d!\n", 15); // now buf contains "The number is 15!\n" (terminated with <code>\0</code>)</li>
- In this client-server communication, we will use the following conventions:
Implement
do_remote_list_database
anddo_remote_find_all_matches
. These will be very similar to the non-remote versions you implemented for lab 6.Test your server with the the
nc
client.nc 127.0.0.1 20000
If the previous manual test looks good to you, you can run the script
./test_server.sh
to do an automated test.
Failed to bind issue
In case you encounter this issue, most likely it is because the port (20000) that you want to open is occupied. To solve this problem, run the following command in Linux terminal:
fuser -k 20000/tcp
If the problem still persists, wait for 60 seconds (the timeout in Linux kernel) and try again.
Create a Client
The next step is to make your own version of nc
. This will be very similar
to the local.c
file, but have significantly less code. The entire purpose of
the client is to connect to a server and then send it whatever you type.
SIDE NOTE: As you work on implementing the client, you may see some strange
behavior where the server's responses seem "behind" where they should be! For
example, listing the database may only show the first entry and other entries
show up after you type a second command. This is because sockets expect one
send()
to be paired with one recv()
. It is OK if you don't fix this
"delay" error in this lab, but think about ways to solve the problem.
Okay, let's begin:
Open up
client.c
. There are a couple of functions with loops:handleLocalInput
should contain a loop that can only do two things: connect to a server or quit.do_connect_to_server
should contain a loop that will keep communicating with the server until it closes the connection. This client will allow you to connect to many servers in sequence.- To get the port number to connect. You need to convert some numbers you
type from the keyboard to an
int
. To convert a number string (a string with all number characters) to an int, you can callatoi(buf)
, wherebuf
is the number string. For example,char buf[4] = {'2', '4', '6', '\0'}; int num = atoi(buf); // Now num will be 246.</li>
Implement
handleLocalInput
. There's not much to do, and it will look like yourhandleLocalInput
from lab 6 but with fewer commands. The commands to implement are documented in the file.Implement
do_connect_to_server
. This function does the following until the server closes the socket:- receive data from the server
- print what it received
- get a line of input from you
- send your input to the server
Test your client with the
./example_server
executable provided.If the previous manual test looks good to you, you can run the script
./test_client.sh
to do an automated test.
Test your client and server
Finally, make sure your server and your client can talk to each other.
- Try using both yours and your partner's laptop to connect across a network.
- Find another team and try communicating with their client and server.
- If you notice any strange behaviors in your client when using your client and server together, it is most likely due to the problem of multiple send and one recv. No need to solve this problem now. We will solve it in the next lab.
Finishing the Lab
- Ensure your name and your partner's names are on all the files you edited.
- Make sure you passed both
./test_server.sh
and./test_client.sh
- Ensure both your names are on all of the files you edited. Both of you should submit a copy of the code on Gradescope.
- Upload any files you modified (
server.c client.c
) to Gradescope