Write a program that enables two users to chat using JavaFX, threads, sockets. I
ID: 3834334 • Letter: W
Question
Write a program that enables two users to chat using JavaFX, threads, sockets.
Implement one user as the server and the other as the client.
The server has two text areas: One for entering text and the other(non editable) for displaying text received from the client. When the user presses the enter key , the current line is send to the client.
The client too has two text areas: One for entering text and the other(non editable) for displaying text received from the server. When the user presses the enter key , the current line is send to the server.
Please use JavaFx and not swing thanks .
Explanation / Answer
chat message.java
01
import java.io.*;
02
/*
03
* This class defines the different type of messages that will be exchanged between the
04
* Clients and the Server.
05
* When talking from a Java Client to a Java Server a lot easier to pass Java objects, no
06
* need to count bytes or to wait for a line feed at the end of the frame
07
*/
08
public class ChatMessage implements Serializable {
09
10
protected static final long serialVersionUID = 1112122200L;
11
12
// The different types of message sent by the Client
13
// WHOISIN to receive the list of the users connected
14
// MESSAGE an ordinary message
15
// LOGOUT to disconnect from the Server
16
static final int WHOISIN = 0, MESSAGE = 1, LOGOUT = 2;
17
private int type;
18
private String message;
19
20
// constructor
21
ChatMessage(int type, String message) {
22
this.type = type;
23
this.message = message;
24
}
25
26
// getters
27
int getType() {
28
return type;
29
}
30
String getMessage() {
31
return message;
32
}
33
}
client.java
001
import java.io.*;
002
import java.net.*;
003
import java.text.SimpleDateFormat;
004
import java.util.*;
005
006
/*
007
* The server that can be run both as a console application or a GUI
008
*/
009
public class Server {
010
// a unique ID for each connection
011
private static int uniqueId;
012
// an ArrayList to keep the list of the Client
013
private ArrayList<ClientThread> al;
014
// if I am in a GUI
015
private ServerGUI sg;
016
// to display time
017
private SimpleDateFormat sdf;
018
// the port number to listen for connection
019
private int port;
020
// the boolean that will be turned of to stop the server
021
private boolean keepGoing;
022
023
024
/*
025
* server constructor that receive the port to listen to for connection as parameter
026
* in console
027
*/
028
public Server(int port) {
029
this(port, null);
030
}
031
032
public Server(int port, ServerGUI sg) {
033
// GUI or not
034
this.sg = sg;
035
// the port
036
this.port = port;
037
// to display hh:mm:ss
038
sdf = new SimpleDateFormat("HH:mm:ss");
039
// ArrayList for the Client list
040
al = new ArrayList<ClientThread>();
041
}
042
043
public void start() {
044
keepGoing = true;
045
/* create socket server and wait for connection requests */
046
try
047
{
048
// the socket used by the server
049
ServerSocket serverSocket = new ServerSocket(port);
050
051
// infinite loop to wait for connections
052
while(keepGoing)
053
{
054
// format message saying we are waiting
055
display("Server waiting for Clients on port " + port + ".");
056
057
Socket socket = serverSocket.accept(); // accept connection
058
// if I was asked to stop
059
if(!keepGoing)
060
break;
061
ClientThread t = new ClientThread(socket); // make a thread of it
062
al.add(t); // save it in the ArrayList
063
t.start();
064
}
065
// I was asked to stop
066
try {
067
serverSocket.close();
068
for(int i = 0; i < al.size(); ++i) {
069
ClientThread tc = al.get(i);
070
try {
071
tc.sInput.close();
072
tc.sOutput.close();
073
tc.socket.close();
074
}
075
catch(IOException ioE) {
076
// not much I can do
077
}
078
}
079
}
080
catch(Exception e) {
081
display("Exception closing the server and clients: " + e);
082
}
083
}
084
// something went bad
085
catch (IOException e) {
086
String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + " ";
087
display(msg);
088
}
089
}
090
/*
091
* For the GUI to stop the server
092
*/
093
protected void stop() {
094
keepGoing = false;
095
// connect to myself as Client to exit statement
096
// Socket socket = serverSocket.accept();
097
try {
098
new Socket("localhost", port);
099
}
100
catch(Exception e) {
101
// nothing I can really do
102
}
103
}
104
/*
105
* Display an event (not a message) to the console or the GUI
106
*/
107
private void display(String msg) {
108
String time = sdf.format(new Date()) + " " + msg;
109
if(sg == null)
110
System.out.println(time);
111
else
112
sg.appendEvent(time + " ");
113
}
114
/*
115
* to broadcast a message to all Clients
116
*/
117
private synchronized void broadcast(String message) {
118
// add HH:mm:ss and to the message
119
String time = sdf.format(new Date());
120
String messageLf = time + " " + message + " ";
121
// display message on console or GUI
122
if(sg == null)
123
System.out.print(messageLf);
124
else
125
sg.appendRoom(messageLf); // append in the room window
126
127
// we loop in reverse order in case we would have to remove a Client
128
// because it has disconnected
129
for(int i = al.size(); --i >= 0;) {
130
ClientThread ct = al.get(i);
131
// try to write to the Client if it fails remove it from the list
132
if(!ct.writeMsg(messageLf)) {
133
al.remove(i);
134
display("Disconnected Client " + ct.username + " removed from list.");
135
}
136
}
137
}
138
139
// for a client who logoff using the LOGOUT message
140
synchronized void remove(int id) {
141
// scan the array list until we found the Id
142
for(int i = 0; i < al.size(); ++i) {
143
ClientThread ct = al.get(i);
144
// found it
145
if(ct.id == id) {
146
al.remove(i);
147
return;
148
}
149
}
150
}
151
152
/*
153
* To run as a console application just open a console window and:
154
* > java Server
155
* > java Server portNumber
156
* If the port number is not specified 1500 is used
157
*/
158
public static void main(String[] args) {
159
// start server on port 1500 unless a PortNumber is specified
160
int portNumber = 1500;
161
switch(args.length) {
162
case 1:
163
try {
164
portNumber = Integer.parseInt(args[0]);
165
}
166
catch(Exception e) {
167
System.out.println("Invalid port number.");
168
System.out.println("Usage is: > java Server [portNumber]");
169
return;
170
}
171
case 0:
172
break;
173
default:
174
System.out.println("Usage is: > java Server [portNumber]");
175
return;
176
177
}
178
// create a server object and start it
179
Server server = new Server(portNumber);
180
server.start();
181
}
182
183
/** One instance of this thread will run for each client */
184
class ClientThread extends Thread {
185
// the socket where to listen/talk
186
Socket socket;
187
ObjectInputStream sInput;
188
ObjectOutputStream sOutput;
189
// my unique id (easier for deconnection)
190
int id;
191
// the Username of the Client
192
String username;
193
// the only type of message a will receive
194
ChatMessage cm;
195
// the date I connect
196
String date;
197
198
// Constructore
199
ClientThread(Socket socket) {
200
// a unique id
201
id = ++uniqueId;
202
this.socket = socket;
203
/* Creating both Data Stream */
204
System.out.println("Thread trying to create Object Input/Output Streams");
205
try
206
{
207
// create output first
208
sOutput = new ObjectOutputStream(socket.getOutputStream());
209
sInput = new ObjectInputStream(socket.getInputStream());
210
// read the username
211
username = (String) sInput.readObject();
212
display(username + " just connected.");
213
}
214
catch (IOException e) {
215
display("Exception creating new Input/output Streams: " + e);
216
return;
217
}
218
// have to catch ClassNotFoundException
219
// but I read a String, I am sure it will work
220
catch (ClassNotFoundException e) {
221
}
222
date = new Date().toString() + " ";
223
}
224
225
// what will run forever
226
public void run() {
227
// to loop until LOGOUT
228
boolean keepGoing = true;
229
while(keepGoing) {
230
// read a String (which is an object)
231
try {
232
cm = (ChatMessage) sInput.readObject();
233
}
234
catch (IOException e) {
235
display(username + " Exception reading Streams: " + e);
236
break;
237
}
238
catch(ClassNotFoundException e2) {
239
break;
240
}
241
// the messaage part of the ChatMessage
242
String message = cm.getMessage();
243
244
// Switch on the type of message receive
245
switch(cm.getType()) {
246
247
case ChatMessage.MESSAGE:
248
broadcast(username + ": " + message);
249
break;
250
case ChatMessage.LOGOUT:
251
display(username + " disconnected with a LOGOUT message.");
252
keepGoing = false;
253
break;
254
case ChatMessage.WHOISIN:
255
writeMsg("List of the users connected at " + sdf.format(new Date()) + " ");
256
// scan al the users connected
257
for(int i = 0; i < al.size(); ++i) {
258
ClientThread ct = al.get(i);
259
writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
260
}
261
break;
262
}
263
}
264
// remove myself from the arrayList containing the list of the
265
// connected Clients
266
remove(id);
267
close();
268
}
269
270
// try to close everything
271
private void close() {
272
// try to close the connection
273
try {
274
if(sOutput != null) sOutput.close();
275
}
276
catch(Exception e) {}
277
try {
278
if(sInput != null) sInput.close();
279
}
280
catch(Exception e) {};
281
try {
282
if(socket != null) socket.close();
283
}
284
catch (Exception e) {}
285
}
286
287
/*
288
* Write a String to the Client output stream
289
*/
290
private boolean writeMsg(String msg) {
291
// if Client is still connected send the message to it
292
if(!socket.isConnected()) {
293
close();
294
return false;
295
}
296
// write the message to the stream
297
try {
298
sOutput.writeObject(msg);
299
}
300
// if an error occurs, do not abort just inform the user
301
catch(IOException e) {
302
display("Error sending message to " + username);
303
display(e.toString());
304
}
305
return true;
306
}
307
}
308
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.