I have implemented a simple client-server solution using Java sockets and useful classes from java.util.concurrent
.
The communication protocol is rather simple:
- Client sends a string with the appended
request_info#
. - A server responds to a client with the message that provides a description on how to use a server.
- If client sends
server_time
then a server will send back a current server time. - If client sends a
quit
- a server will process a client disconnect. - A default case: client sends an arbitrary string then a server simply bounces it back to a client.
I have tested my solution by spawning a fixed number of client threads. Each of them sends a command from a txt file to a server.
Some technical remarks:
- A configuration for the client and server (such as port number and host address) is loaded from an .xml file.
- To start a server:
java –jar app.jar –server –config config.xml
. - To start a client:
java –jar app.jar –client –config config.xml
.
I would like to seek any suggestions on whether I have correctly implemented the following class (serves as an abstraction for a message between client and server):
public class Message {
private Socket socket;
private String message;
private static Logger logger = Logger.getLogger(Message.class);
public void setSocket(Socket socket) {
this.socket = socket;
}
public String getMessage() {
return message;
}
public Socket getSocket() {
return socket;
}
public void setStringMessage(String message) {
this.message = message;
}
public void setMessageInputSources(InputStream inputStream) throws IOException {
String s;
BufferedReader bufferRead = new BufferedReader(new InputStreamReader(inputStream));
s = bufferRead.readLine();
this.message = s;
}
public synchronized String getCommand() {
String stringMessage = this.getMessage();
return StringUtils.upperCase(stringMessage.split("#")[0]);
}
public void send(String message) throws IOException{
DataOutputStream dataOutputStream = new DataOutputStream(this.socket.getOutputStream());
dataOutputStream.writeUTF(message);
dataOutputStream.flush();
this.setStringMessage(message);
}
public Message receive() throws IOException {
String data;
DataInputStream dataInputStream = new DataInputStream(this.socket.getInputStream());
data = dataInputStream.readUTF();
this.setStringMessage(data);
return this;
}
@Override
public String toString() {
return this.message;
}
}
Do I properly manage a case when all client threads are done with their jobs and I shut down an application? Are there any improvements to be made?
public class MainTest {
private static final int NUMBER_OF_THREADS = 4;
public static void main(String[] args) throws IOException, InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(NUMBER_OF_THREADS);
Thread serverThread = new Thread(() -> Server.start(new File("config.xml"), countDownLatch));
serverThread.setName("server_thread");
Thread clientThread = new Thread(() -> {
try {
new Client(new File("config.xml"), new FileInputStream("commands.txt")).start(NUMBER_OF_THREADS, countDownLatch);
} catch (ExecutionException | IOException | InterruptedException e) {
e.printStackTrace();
}
});
clientThread.setName("Running client threads, " + 10);
serverThread.start();
clientThread.start();
if(countDownLatch.getCount() == 0){
System.exit(0);
}
}
}
Here is the link to my project: GitHub Repository