-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatServer.java
More file actions
157 lines (138 loc) · 5.35 KB
/
ChatServer.java
File metadata and controls
157 lines (138 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Server
* - The chat server's primary job is to pass messages from all clients to all clients.
* - The server will need to allow connections from clients.
* - Get a "handle" for the client
* - receive messages
* - send the messages to all connected clients.
*
* start the ChatServer program on the server host.
* USAGE: java ChatServer port
* optional command line arguments:
* [port]: the port number to listen and accept the incoming connection request, 8000 by default.
*
* @author: Yu Jin
*/
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
/**
* ChatServer models a server for a 1-to-N Server-client architechture based chatting room.
* It will sit on a specified port number waiting for clients to request connections.
* Once a client is connected to this server, it will keep recieving all the message sent from all connected clients.
*/
public class ChatServer {
public static final int DEFAULT_PORT = 8000;
public static final int MAX_MSG_Q_SIZE = 1000;
private final ArrayList<Socket> connections = new ArrayList<Socket>();
private final BlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>(MAX_MSG_Q_SIZE);
public static void main(String[] args) {
final int port = (args.length > 0) ? Integer.parseInt(args[0]) : DEFAULT_PORT;
final ChatServer server = new ChatServer();
new Thread(){ public void run(){ server.acceptConnectionReq(port); }}.start();
new Thread(){ public void run(){ server.distributeMessage(); }}.start();
}
/**
* Create a server socket on the specified port and keep listening on it and accepting coming in connection request.
* @param port the port on which to start the server socket.
*/
private void acceptConnectionReq(int port) {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Start service on [" + port + "] successfully!");
while(true) {
Socket clientSocket = serverSocket.accept();
addClient(clientSocket);
new MessageCollector(clientSocket, this).start();
}
}
catch(IOException e) {
System.err.println("Failed to start service on port [ "+port+" ].\nPlease check whether port is available or choose another free port.");
System.err.println(e.toString());
}
finally{
if(serverSocket != null){
try{
serverSocket.close();
}
catch(IOException e) {
}
}
}
}
private synchronized void addClient(Socket client){
connections.add(client);
}
private synchronized void removeClient(Socket client){
connections.remove(client);
}
/**
* Keep removing messages from the message queue and sending them to all the clients currently connected.
*/
private void distributeMessage() {
while(true) {
try {
String msg = msgQueue.take();
synchronized(this){
for(Socket client : connections) {
try{
new PrintWriter(client.getOutputStream(), true).println(msg);
}
catch (IOException e) {
}
}
}
}
catch (InterruptedException e){
}
}
}
/**
* A Thread class to collect messages from a specified socket.
* @param clientSocket the client socket from which to collect messages.
*/
private class MessageCollector extends Thread {
private Socket clientSocket;
private String username;
private ChatServer server;
/**
* Construct a MessageCollector thread.
* @param clientSocket the client socket from which to collect messages.
*/
public MessageCollector(Socket clientSocket, ChatServer server) {
this.clientSocket = clientSocket;
this.server = server;
}
/**
* Run the thread to collect messages coming from the client socket.
*/
public void run() {
try {
Scanner incomingMsg = new Scanner(clientSocket.getInputStream());
username = incomingMsg.nextLine();
msgQueue.put(username + " joins the room!");
while (incomingMsg.hasNextLine()){
String msg = incomingMsg.nextLine();
System.out.println(msg);
msgQueue.put(msg);
}
msgQueue.put(username + " left the room!");
server.removeClient(clientSocket);
}
catch(Exception e){
}
finally {
if(!clientSocket.isClosed()){
try {
clientSocket.close();
}
catch(IOException e) {
}
}
}
}
}
}