This is the last lab! Almost there...
In this lab, we will learn the important skill of distributed programming using socket programming in C and the socket API. A socket is similar to the pipe abstraction between two processes on the same machine but in this lab we will create a reliable byte-stream “pipe” that uses TCP between client and server processes running on different machines over the Internet. Socket programming is very cool and the basis of the vast majority of Internet programming.
In this lab, you will write a client and a server. You’ll start with writing a client that will communicate with a server that we put up on the web. Then you will write the server.
We will use TCP socket programming as part of the robotics project. In this lab, we give you a lot of the code so it’s not too taxing. However, don’t blindly use it to simply complete the assignment - understand the code. You will need to nail socket programming for the project, as mentioned above.
OK, let’s get going.
The assignment includes two parts. First, implement a TCP client that interacts with an existing server - that we have written and that is “always on”. After that write the TCP server side using an IP address and port of your choosing and run your client and server. The server should act in the exact same way as our server.
First the client part:
The background to this programming idea is that a client can interacts with a sensor and gets real-time sensor readings, such as, temperature, humity, and light. Here the “sensor” is the server software. We will use real sensors in the robotics project.
Implement a client that retrieves temperature, humidity and light data from a remote server. The server runs on green.cs.dartmouth.edu and you will need the IP address; you can get that by typing “host” at the terminal
green.cs.dartmouth.edu has address 22.214.171.124
A client can access the server at IP address 126.96.36.199 on port 5567. The server is up and running now.
The client should connect to the server, stay connected, and retrieve a number of readings similar to the screen dump show below. The client can request readings from the server as many times as you want, however, the reading values returned by server will only be modified every second. For example. the client requests temperature and then waits for the server to respond with the temperature, then it requests humidity and again waits for the server response, finally, the client requests light and gets the current light reading. The server will not change the value of the sensor data (i.e., temp, hum, light) until a second has passed. In essense, the server emulates a real live sensor where the sensor data changes over time. The client can request sensor data in any order (e.g., hum, temp, light) – the example above is just an example – and the server will respond accordingly. The client should connect to the server and request a new set of sensor data (i.e., temp, light, hum) every second TIP: your client needs to sleep for one second before it issues a new request. Once the client has cycled through all the data (e.g., the server starts to repeat itself after 20 seconds) it should disconnect/close the connection.
The server (i.e., the child process forked to handle the connection) will also close when the client issues a close. Therefore, the server is capable of handling concurrent clients. You should design for that went you code up the server; this is similar in design to the echoConServer.c found in the lecture notes.
Note, that the “listening server” should always remain active. You can use similar printf statements for your client output as shown below. Here is a high level description of the server functionality. The server should compute the time when the client sets up a connection (just after the accept) and when it gets a request. It should compute the difference in the time readings and normalizes that to index the current temp., hum., light data (read into memory from the data files). Note, that the data in the files is limited (not 100s of readings) so you might wrap around while running the client/server. The idea here is that when the client connects to the server the server resets some representation of the client’s clock to zero (e.g., the clock starts from zero) and waits for requests from the client. When it gets a request some time later (e.g., 0.5 sec later) it computes the new client clock time (e.g., current time - clock time – 0.5 - 0) and indexes the data based on that time. In this example, the time difference is less than a second so the server will send the current data (e.g., the current temp if temperature is requested); if however, the time difference was greater than one second but less than two seconds it would get the next reading from the data (tip: the server needs to read the computers wall clock (i.e., clock time, as mentioned above) when the client first connects, e.g., using the time() function. The server needs to read the time again and compute the difference when a request is received. It uses the difference between the current time and clock time (which will not be zero as in the example above) to determine how to index the data copied in from the three files into arrays).
The data can be retrieved when the client sends the following strings "TEMPERATURE", "HUMIDITY" or "LIGHT" to the server. Once one of the three strings is received at the server (e.g., temperature), the server will immediately return a 2-byte string representing the integer value of the sensor reading. You should display readings to the screen. For example:
Once you have written a working client and it works with the existing server, discussed above, then you need to write a replacement server that does exactly the same. The idea is that you first write the client that works with an existing server. Then you write the server and run your client and server together.
Next, implement the concurrent server part of the program. The actual data can be retrieved from a set of files:
Each file contains the last 20 readings of the temperature, humidity and light sensors (one read per second for each category). The 20 readings are formatted as a list, one reading per line. The files are the following:
The server is simulating a sensor such as the mote sensors you see around Sudikoff - that provides readings of temperature, light and humidity. In this case, you will copy these files into the same directory as your server and the server will open each file, read in all sensor values, and serve every request from the client. If a client requests temperature, the server will return a certain temperature sample from temperature.dat according to the time of the connection. Starting from the first value of temperature.dat when a connection is established, every second the server should return the next value in temperature.dat upon request. If EOF is reached, the server should wraps around and start from the beginning of the file again. For this assignment you will have to work out the details of how the commands and responses interaction between the client and server, respectively.
The server is responsible for reading in the data, accepting client connections and sending out the right data according to the commands sent by clients.
Submit using SVN:
Submit the assignment using Subversion Versions System (SVN). Use SVN to sign in your source tree.
Change to your labs directory cd ~/cs50/labs This directory contains your lab7 directory where your solutions are found.
Please make sure that the labs directory contains a simple text file, named README, describing anything “unusual” about how your solutions should be located, executed, and considered; and a Makefile to build the source.
Coding style: Excellent code required.
The final software should be include of the following components:
Again, you should also provide a Makefile to build your program (one for the client and one for the server) and a concise README file describing briefly your design choices and how to run the program.
Tip: Make sure you always logout when you are done and see the prompt to login again before you leave the terminal.