Lecture note 5
Download
Report
Transcript Lecture note 5
COMPS311F
Li Tak Sing
Case study: a multithreaded chat
server
The source contains 3 files:
ChatServer //the chat server
ChatThread //the thread on the server side to handle a client
ChatClient //the client
The source can be obtained at:
http://plbpc001.ouhk.edu.hk/~mt311f/2010-sep/chat.zip
ChatServer
The ChatServer class is the main program for the chat server.
It will create a ServerSocket at port 12345. For each of the
incoming requests, a ChatThread will be created to entertain
the request.
It is a subclass of JFrame. The window is used to display
information regarding the connected clients and messages
passed.
ChatServer
The upper textfields will
show the connected
clients.
The central textarea will
show the messages from
the clients.
Attributes of ChatServer
Vector<ChatThread> threads; //connected clients
JTextField clientText; //for displaying the connected clients
JTextArea text; //for displaying the messages from the
clients
Methods of ChatServer
synchronized public void addThread(ChatThread th);
//this method adds the ChatThread to threads.
synchronized public void removeThread(ChatThread th) ;
//this method removes the ChatThread from threads.
synchronized public void broadcast(String st);
//this method is used to send a message to all connected
clients.
ChatThread
It is created to entertain an individual request.
It is a subclass of Thread.
When a ChatThread is created, it will be added to threads of
ChatServer by using the addThread method of ChatServer.
The run method of ChatThread will continuously read from
the corresponding client. When a message is read from the
client, it will be broadcast to all connected clients through
the broadcast method of ChatServer.
It also provide a sendMessage method for sending a message
to the corresponding client.
Attributes of ChatThread
String name; //name of the client
Socket socket; //socket of the connection between the
server and the client.
ChatServer server; //the ChatServre
DataInputStream input; //the input stream for the
connection with the client.
DataOutputStream output; //the output stream
Constructor of ChatThread
public ChatThread(java.net.Socket s, ChatServer server)
This construct allows ChatThread to record the socket and the
server. The socket is used to create the data streams. The
server is used to broadcast a message.
Methods of ChatThread
public synchronized void sendMessage(String st) throws
IOException ; //this method is used to send a message to
the client
public void run(); //this will continuously read from the
client. After reading a message, it will invoke the server's
broadcast method to send the message to all connected
clients.
ChatClient
It is the chat client.
It is a subclass of JFrame.
The top panel contains a
textfield for the user to type
in a name. This will be the id
of the client in the chat
system.
The central textarea is used
to display all messages from
clients.
The bottom panel contains a
textfield for the user to type
in a message.
Attributes of ChatClient
JTextField name; //This allows the user to type in name
JTextArea messages; //This is used to display messages from
all connected clients.
JTextField text; //This allows the user to type in message to
be sent to all clients.
DataInputStream input; //This is the input stream for the
connection.
DataOutputStream output; //The output stream.
Constructor of ChatClient
public ChatClient() ;
//the constructor does all things. It setups the window. All
listeners are created using anonymous classes. A thread is
created to continuously read from the server. When a
message is read, it will be appended to the central textarea,
messages.
Implementation of constructor of
ChatServer
...
try {
java.net.ServerSocket ss = new
java.net.ServerSocket(12345);
while (true) {
java.net.Socket s = ss.accept();
ChatThread thread = new ChatThread(s, this);
}
} catch (Exception e) {
e.printStackTrace();
}
...
Implementation of methods of
ChatServer
synchronized public void addThread(ChatThread th) {
threads.add(th);
String st = "";
for (ChatThread thread:threads) {
st+=thread.name()+" ";
}
clientText.setText(st);
}
Implementation of methods of
ChatServer
synchronized public void removeThread(ChatThread th) {
threads.remove(th);
String st="";
for (ChatThread thread:threads) {
st+=thread.name()+" ";
}
clientText.setText(st);
}
Implementation of methods of
ChatServer
synchronized public void broadcast(String st) {
text.append(st);
java.util.Vector<ChatThread> removedThreads = new
java.util.Vector<ChatThread>();
for (ChatThread th : threads) {
try {
th.sendMessage(st);
} catch (Exception e) {
removedThreads.add(th);
}
}
for (ChatThread th : removedThreads) {
removeThread(th);
}
}
Implementation of constructor of
ChatThread
public ChatThread(java.net.Socket s, ChatServer server) {
socket=s;
this.server=server;
try {
output=new java.io.DataOutputStream(socket.getOutputStream());
input=new java.io.DataInputStream(socket.getInputStream());
name=input.readUTF();
server.addThread(this);
start();
}
catch (Exception e) {
e.printStackTrace();
}
}
Implementation of methods of
ChatThread
public synchronized void sendMessage(String st) throws
IOException {
output.writeUTF(st);
}
Implementation of methods of
ChatThread
public void run() {
try {
while (true) {
String st=input.readUTF();
server.broadcast(name+":"+st);
}
}
catch (Exception e) {
server.removeThread(this);
}
}
The ActionLister of the connect
button
public void actionPerformed(ActionEvent e) {
if (button.getText().equals("connect")) {
try {
s = new java.net.Socket("127.0.0.1", 12345);
input = new
java.io.DataInputStream(s.getInputStream());
output = new
java.io.DataOutputStream(s.getOutputStream());
output.writeUTF(name.getText());
messages.append("connected\n");
button.setText("disconnect");
The ActionLister of the connect
button
new Thread() {
public void run() {
try {
while (true) {
String st = input.readUTF();
messages.append(st);
}
} catch (Exception e) {
messages.append("Disconnected\n");
button.setText("connect");
}
}
}.start();
The ActionLister of the connect
button
} catch (Exception ee) {
button.setText("connect");
messages.append("disconnected");
}
} else {
try {
input.close();
output.close();
s.close();
button.setText("connect");
messages.append("disconnected");
} catch (Exception ee) {
}
}