Programming Assignment 4
CS 33600
Network Programming
Spring, 2026

This assignment makes use of the files contained in this zip file. This assignment is due Friday, May 1.

This assignment is based on the code examples from the "end-of-message" sub folder of simple_client-server_pairs.zip and the explanations in Readme_11_sockets.md, in particular, the section The end-of-message problem.

This assignment is based on these two client/server pairs from the "end-of-message" folder.

In this assignment you will implement four client/server pairs that implement four more "addition protocols".

The addition servers in the end-of-message folder accept an arbitrary number of sequences of integers to add together. Those servers use the end-of-stream (eof) condition to know when there are no more sequences to add up. The addition servers in this assignment will use either a counter or a sentinel to know when there are no more sequences to add up.

Using the end-of-stream condition to denote the end of the sequences has a problem. If the server gets an end-of-stream condition before it sees an expected sentinel, or before it receives a given count of integer values, then the server knows that this is a premature end-of-stream (in the middle of a sequence of integer values), which means that there is a problem with its communication from the client. But if the server gets an end-of-stream condition right after a sentinel, or right after a completed count of integer values (in other words, an eof right after a completed sequence of integer values), then the server assumes that this is a normal, not a premature, end-of-stream. But it may be a premature end-of-stream. The client may still have data to send, but the connection was interrupted. Using end-of-stream to denote the end of all the data is unreliable. The server does not know if it received all the data that the client intended to send. The server just guesses that the client really has sent all of its intended data.

Using either a sentinel value or a count value to denote the end of all the data solves this unreliability issue between the client and the server. If the server gets an end-of-stream condition before the final sentinel, or before the expected number of complete sequences, then the server knows that it has received a premature end-of-stream and that there must be a problem with its connection to the client. (A premature end-of-stream condition can never happen when a program reads from a file. This is another example of how streams over a network do not act like traditional file streams. File streams are assumed to be reliable.)

The servers

should use a sentinel to determine when there are no more sequences expected from the client. The server AdditionServer_v1_Hw4.java should use a counter to know when it has read the last integer in a sequence. The server AdditionServer_v2_Hw4.java should use a sentinel to know when it has read the last integer in a sequence.

The servers

should use a counter to determine when there are no more sequences expected from the client. The server program AdditionServer_v3_Hw4.java should use a counter to know when it has read the last integer in a sequence. The server program AdditionServer_v4_Hw4.java should use a sentinel to know when it has read the last integer in a sequence.

In summary, the four client/servers pairs should implement the following protocols for denoting the end of each sequence and then the end of all the sequences.

The sentinel values can be any negative integer. When a sentinel is used to denote the end of a sequence, then the sequence values must all be positive integers (client/server pairs v2 and v4).

Here is what three client requests look like for each of the four client/server pairs.

    4 1 2 3 4 5 -1 -2 -3 -4 -5 3 10 -11 12 -1

    1 2 3 4 -1 1 2 3 4 5 -1 10 11 12 -1 -1

    3 4 1 2 3 4 5 -1 -2 -3 -4 -5 3 10 -11 12

    3 1 2 3 4 -1 1 2 3 4 5 -1 10 11 12 -1

Make sure you understand why each line represents exactly three requests from a single client and make sure that you can determine what numbers are in each request.

The client programs read from their standard input stream, System.in, the data that they send to the server.

The four client programs are written for you. You should not make any changes to the implementations of the four client programs. You are responsible for completing the four server programs. Each of the four server programs has the "boiler plate" code of making the socket connection to the client already implemented. You need to implement the "application layer protocol" part of each server.

The client programs send the integer values as strings of decimal digits with a single space character between every two integer values. The servers should use the nextInt() method from the Scanner class to read and parse the integers values from their socket's input stream.

Right after a client sends a complete sequence of integer values to the server, the client expects back from the server a single message containing the sum of the sequence. After the client gets the server's response, the client sends the next sequence of integer values to the server. Similarly, the server should keep a running total of the values in a sequence and send the final value of the sequence sum back to the client when the sequence is complete. (The server should not store all the received data in an array or list. That would be an inefficient waste of computer memory. The server should process each input value immediately after receiving it.) After the server has sent the client the sum, the server should expect another sequence of integer values.

In the zip file there are data files data_v1.txt, data_v2.txt, data_v3.txt, and data_v4.txt that provide test data for each client/server pair. To use the test data, open a console window and run a server from the command-line.

   > java AdditionServer_v1_Hw4

Then open another console window and run the companion client from the command-line with the appropriate data file redirected into the client.

  > java AdditionClient_v1_Hw4  <  data_v1.txt

The resulting output from the server should exactly match data_v1_server_results.txt (except for the pid, hostname, ip address, and client port numbers).

In the zip file there is a script file, run_tests.cmd, that will automatically run these tests for you, but you need to manually look at the results to see if they are correct.

Make sure you test that your servers can accept multiple connections, one after another. If you have a bug in your server, it might handle its first client connection correctly, but not be able to properly handle a second or third client. My grading scripts will connect your servers to multiple clients.

Turn in a zip file called CS336Hw4Surname.zip (where Surname is your last name) containing your versions of

This assignment is due Friday, May 1.