1°/ Interactive client in a console
- We assume that the client executes within a terminal, and the requests are given bu the user via the keyboard.
- From user's point of view, sending a request consists in typing a line that represents what he wants to ask to the server. In the followng template, the line format for the user is : request_name param1 param2 ... (NB : it is quite simialr to the format of the real request that is sent by the client, see below)
- From the client's point of view, this line must be analyzed and translated into a request to the server.
- The format of the request to the server is : req_identifier client_id param1 param2 ...
- We assume that the identifier of each request is a number 1, 2, ... except the "quit" request that means the client wants to disconnect from the server.
- The client id is a unique identifier that is sent to the client juste after the acception of the connection.
- We also assume that all communications are done using text (=> using PrintStream and BufferedReader), in order to facilitate debug and to comply with the fact that embedded systems are not necessarily able to use Java to communicate.
- Finally, we assume that the client application is organized in 2 classes: Client and ClientTCP
Client.java :
import java.net.*;
import java.io.*;
class Client {
public static void usage() {
System.err.println("usage : java Client ip_server port");
System.exit(1);
}
public static void main(String[] args) {
if (args.length != 2) {
usage();
}
ClientTCP client = null;
try {
int port = Integer.parseInt(args[1]);
client = new ClientTCP(args[0], port);
client.requestLoop();
}
catch(NumberFormatException e) {
System.err.println("invalid port number");
System.exit(1);
}
catch(IOException e) {
System.err.println("cannot communicate with server");
System.exit(1);
}
}
}
ClientTCP.java :
import java.io.*;
import java.net.*;
import java.util.*;
class ClientTCP {
Socket sockComm;
BufferedReader br; PrintStream ps;
String id; // the client id sent by the server with request 0
public ClientTCP(String serverIp, int serverPort) throws IOException {
sockComm = new Socket(serverIp, serverPort);
ps = new PrintStream(sockComm.getOutputStream());
br = new BufferedReader(new InputStreamReader(sockComm.getInputStream()));
// get my id
id = br.readLine();
}
public void requestLoop() throws IOException {
boolean stop = false;
String reqLine = null;
BufferedReader consoleIn = null;
String[] reqParts = null;
consoleIn = new BufferedReader(new InputStreamReader(System.in));
while (!stop) {
System.out.print("Client> ");
reqLine = consoleIn.readLine();
reqParts = reqLine.split(" ");
if ("req1".equals(reqParts[0])) {
String req = "1 "+id+" ";
// adding to req parameters obtined from reqParts[1] reqParts[2], ...)
ps.println(req);
String answer = br.readLine();
// processing answer
}
else if ("req2".equals(reqParts[0])) {
String req = "2 "+id+ " ";
// adding to req parameters obtained from reqParts[1] reqParts[2], ...)
ps.println(req);
String answer = br.readLine();
// processing answer
}
/* etc. with other requests */
else if ("quit".equals(reqParts[0])) {
ps.println("quit");
stop = true;
}
}
}
}
2°/ Server with a single client at a time.
- As for the client, we assume that the server is composed of two classes : Server and ServerTCP
Server.java :
import java.net.*;
import java.io.*;
class Server {
public static void usage() {
System.err.println("usage : java Server port");
System.exit(1);
}
public static void main(String[] args) {
if (args.length != 1) {
usage();
}
ServerTCP server = null;
try {
int port = Integer.parseInt(args[0]);
server = new ServerTCP(port);
server.mainLoop();
}
catch(NumberFormatException e) {
System.err.println("invalid port number");
System.exit(1);
}
catch(IOException e) {
System.err.println("cannot communicate with client");
System.exit(1);
}
}
}
ServerTCP.java :
import java.io.*;
import java.net.*;
import java.util.*;
class ServerTCP {
BufferedReader br;
PrintStream ps;
ServerSocket sockConn;
Socket sockComm;
int idClient;
// other attributes, usefull to process request
public ServerTCP(int port) throws IOException {
idClient = 0;
sockConn = new ServerSocket(port);
}
public void mainLoop() throws IOException {
while(true) {
sockComm = sockConn.accept();
try {
br = new BufferedReader(new InputStreamReader(sockComm.getInputStream()));
ps = new PrintStream(sockComm.getOutputStream());
idClient += 1;
ps.println(idClient); // sending its id to the client
requestLoop();
br.close(); // close stream => close connection
ps.close();
}
catch(IOException e) {
System.out.println("client disconnected");
}
}
}
public void requestLoop() throws IOException {
String req = "";
boolean stop = false;
while(!stop) {
req = br.readLine();
if (req == null) return; // stop loop : suppose that client disconnected
if (req.isEmpty()) continue; // empty req => do nothing special
String[] reqParts = req.split(" ");
if ("1".equals(lst[0])) {
if (reqParts.length != ...) { // check number of params
ps.println("ERR invalid number of paramters");
}
else {
processRequest1(reqParts[1], ... ); // replace ... by a list of reqParts[x]
}
}
else if ("2".equals(lst[0])) {
if (reqParts.length != ...) {
ps.println("ERR invalid number of parameters");
}
else {
processRequest2(reqParts[1], ... ); // replace ... by a list of reqParts[x]
}
}
/* etc. with other requests */
else if ("quit".equals(lst[0])) {
stop = true;
}
}
}
public void processRequest1(String idStr, String param1, String param2, ...) throws IOException {
int id;
try {
id = Integer.parseInt(idStr);
// add here other params to translate into numbers
}
catch(NumberFormatException e) {
ps.println("ERR invalid type of parameter");
return;
}
if (id != idClient) {
ps.println("ERR invalid id");
return;
}
// add here other tests on other parameters
// if all ok,
ps.println("OK");
// process the request and send the result to the client
}
// etc. with other processRequestX() methods
}