Preamble


  • These exercises allow to "softly" discover a basic case of client/server application, written in Java.
  • The client part is in Java but the principles would be the same with an embedded system that must communicate with a server. Moreover, such a system could be based on a real OS (like a raspberry), and the client could be effectively written in Java. 

Exercise 1

  • Create a file named Time.java and copy the following code within.
  • Then fulfill the two methods that are not implemented.
import java.io.*;
 
public class Time {
 
    private int h,m,s;
 
    public Time() {
	h = 0; m = 0; s = 0;
    }
 
    public Time(int h, int m, int s) {
        this.h = h; this.m = m; this.s = s;
    }
 
 
    public String toString() {
        String msg = h+":"+m+":"+s;
        return msg;
    }
 
    public int getH() {
        return h;
    }
 
    public int getM() {
        return m;
    }
 
    public int getS() {
        return s;
    }
 
    public Time clone() {
        return new Time(h,m,s);
    }
 
    public int toSeconds() {
        /* to fill :
 	   returns the time in seconds
        */
    }
 
    public static int[] fromSeconds(int sec) {
        /* to fill :
	sec = a time in seconds
	return sec converted in h,m,s as an array of int
        */
    }
 
    public boolean closeTo(Time time, int gapSec) {
        /* to fill :
 	   must return true if current time is equal to time, +/- gapSec.
	   for example, if this = 12:34:56 and time = 12:35:0, return true if gapSec <= 5,
	   else returns false.
        */
    }
 
    public int gapInSeconds(Time time) {
         /* to fill :
	    return the gap in  seconds between this and time
	    for example, if this = 10:0:0 and time = 11:01:01, return 3661
         */
    }
}
 

 


Exercise 2

  • Thanks to the template given in courses, create files named  Server.java and TimeServer.java , that will make some computations on times sent by the client.
  • Here is the beginning of the "real" server part, TimeServer.java:
import java.io.*;
import java.net.*;
import java.util.*;
 
class TimeServer {
 
    ServerSocket sockConn; Socket sockComm;
    PrintStream ps; BufferedReader br;
    Map<Integer, ArrayList<Time>> map; // the key will be a client_id
    int idClient;
 
    TimeServer(int port) throws IOException {
        sockConn = new ServerSocket(port);
        map = new HashMap<>();
        idClient = 0; // incremented at each connection
    }
    ...
}
 

 

  • Server's principles :
    • wait for a connection,
    • instantiate a PrintStream and a BufferedReader thanks to the communication socket obtained during the connection phase,
    • wait a texte line that contains a request. The line is always composed of fields separated by spaces. The first field is the request identifier, the second field is the client identifier (except for request 0, see below), the next fields are the parameters of the request (if any)
    • process the request and send back the result to the client,
    • wait for a new request. etc.
  • Requests sent by the client are of 4 types:
    • # 0 : ask the server for the client id. Each time a client connects to the server, this latter associates the client to a unique int. This request sends this id to the client. CAUTION : it must be the first request that a client sends. This request also instantiate an ArrayList in map, associated to client_id.
    • # 1 : ask the server to memorize a time. It must be stored on the server in the ArrayList associated to the client id. Request's scheme:
      • client sends a text line with the following format : "1 client_id h m s"
      • server sends back a line with "OK" if client_id and parameters are correct, or "ERR_ID" if client_d does not exist, or "ERR_PARAM" if h, m, or s have incorrect values (i.e. negative, > 23 or 59).
    • # 2 : ask the server to compute the average of stored times associated to the client. Request's scheme:
      • client sends a text line with the following format: "2 client_id"
      • server sends back "ERR_ID" if client_d does not exists, else "OK". In this case, it also sends back the average.
    • # 3 : ask the server if a given time is already stored, within a gap of n seconds. Request's scheme:
      • client sends a text line with the following format: "3 client_id h m s n" (n is the gap in seconds)
      • server sends back a line with "OK" if client_id and parameters are correct, or "ERR_ID" if client_d does not exist, or "ERR_PARAM" if h, m, s, n have incorrect values (i.e. negative, > 23 or 59).
      • If "OK", then the server sends back the answer to the request : "true" or "false".

Exercise 3
 

Create files named Client.java and TimeClient.java according to the template of the courses

  • Client's principles: 
    • connect to the server
    • instanciate a PrintStream and a BufferedReader thanks to the communication socket
    • sends a request #0 to obtain its id.
    • sends a dozen of request #1, for example starting at 10:0:0 and increasing the m and s at each request.
    • sends a request #2
    • sends two requests #3, with one time that is close to a previously stored one, and one that is not.
 

 


Exercice 4

  • Modify the client so it can interact with the user, according to the template given during courses.
  • requests are typed on the keyboard with a relevant format, like:
    • request 1: storetime h,m,s
    • request 2 : average
    • request 3 : find h,m,s,n
  • Client must check if the lines typed by the user match these formats, then translate these lines into correct request to the server.
  • NB: the client should not check if request parameters have correct values.

Exercice 5 (bonus for those who are fast)
  • Modify both client and server to add the following requests:
    • # 4 : ask the server max and min times.
    • # 5 : ask the server for the last time stored by other clients.