-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathChatClient.java
251 lines (219 loc) · 7.81 KB
/
ChatClient.java
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
import PDU.*;
import Threads.*;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import static java.lang.Thread.sleep;
/**
* Course: 5DV167
* Written by: Thomas Sarlin
* @Author Thomas Sarlin
* @Version 1.0 13/10-2016
*/
/**
* Class representing a terminal based chat-application.
* Uses TCP to connect to a given chatserver/nameserver via
* address and port. The server must be running the same PDU-protocol as
* given by the course 5DV167.
*/
public class ChatClient {
private String serverAddress;
private int serverPort;
private String clientName;
private Socket socket;
private CSInThread inThread;
private CSOutThread outThread;
/**
* Constructs a chat-client
* @param identity name of client
* @param serverType ns/cs representing chat-server/name-server.
* @param host address to specified name/chat-server.
* @param port port that the specified server listens to.
* @throws IOException in case the server is invalid/non-existing. or
* if the arguments are invalid.
*/
public ChatClient(String identity, String serverType
, String host,int port) throws IOException, InterruptedException {
checkInput(identity,serverType,host,port);
clientName=identity;
serverAddress=host;
serverPort=port;
System.out.println("Welcome " + clientName);
switch (serverType) {
case "cs":
connectToChatServer();
chat();
break;
case "ns":
connectToNameServer();
selectChatServer();
connectToChatServer();
chat();
break;
}
}
/**
* Checks so that all input arguments are valid.
* @param identity name of client.
* @param serverType ns/cs representing name/chatserver
* @param host address of server
* @param port port of server.
* @throws IOException
*/
private void checkInput(String identity, String serverType
, String host,int port) throws IOException{
if(identity.length()>255){
throw new IOException("Identity larger than 255 characters");
}
else if(!serverType.equals("cs")&&!serverType.equals("ns")){
throw new IOException("Invalid serverType,(cs,ns)");
}
else if(!correctPort(port)){
throw new IOException("Invalid port");
}
}
/**
* Method to connect to name-server.
* @throws IOException if socket is unable to connect.
*/
private void connectToNameServer() throws IOException {
socket = new Socket(serverAddress,serverPort);
new NSCommunication(socket);
}
/**
* Lets the user select Chat-server by writing it's ipv4-address and port.
*/
private void selectChatServer(){
String[] splitAddress;
String[] splitIP;
boolean validInput=false;
while(!validInput) {
System.out.print("Write address and port of selected " +
"server: ");
//Separating IP-address & port
splitAddress = new Scanner(System.in).nextLine().split("\\:");
//Separating all parts of the Ipv4 address.
splitIP = splitAddress[0].split("\\.");
if (splitAddress.length != 2||splitIP.length!=4) {
System.out.println("\n--Invalid format " +
"(xxx.xxx.xxx.xxx:p)--\n");
} else if (correctPort(new Integer(splitAddress[1]))
&&correctAddress(splitAddress[0])) {
serverAddress=splitAddress[0];
serverPort=new Integer(splitAddress[1]);
validInput = true;
}
}
}
/**
* Used to connect to a chat-server
* @throws IOException in case socket is unable to connect/is rejected.
*/
private void connectToChatServer() throws IOException {
System.out.println("Connecting to chat-server.. "
+ "<" + serverAddress +":" + serverPort+ ">");
socket = new Socket(serverAddress,serverPort);
inThread = new CSInThread(socket);
outThread = new CSOutThread(socket);
outThread.start();
inThread.start();
outThread.sendPDU(new PDU_JOIN(clientName));
}
/**
* Used in the select server method to see if ip is within ipv4 range.
* @param address Ipv4-address
* @return representation of the ipv4s validity.
*/
private boolean correctAddress(String address) {
boolean isValid=true;
String[] temp = address.split("\\.");
for(int i =0;i<temp.length;i++)
if((new Integer(temp[i])<0||new Integer(temp[i])>255)){
isValid=false;
System.out.println("\n--IP out of range" +
"(0-255)--\n");
}
return isValid;
}
/**
* Checks if port is within range.
* @param port port to be checked.
* @return representation of the ports validity.
*/
private boolean correctPort(int port){
boolean validPort=true;
if (port<0 | port> 65535) {
System.out.println("\n--Port number out of range" +
"(0-65553)--\n");
validPort=false;
}
return validPort;
}
/**
* The method responsible for running the chat, reading from system in
* and creating a PDU representing the message of the client.
* Chat commands:
* /quit
* /help
* @throws IOException
*/
private void chat() throws IOException, InterruptedException {
Scanner scanner = new Scanner(System.in);
String message;
boolean chat=true;
//Thread that prints PDUs to console.
Thread thread = new Thread(){
@Override
public void run(){
boolean receive= true;
while(receive) {
if (!inThread.queueIsEmpty()) {
if (inThread.pduIsQuit()) {
inThread.printNextPDU();
receive = false;
} else if (inThread.isValidPDU() &&
!inThread.pduIsQuit())
inThread.printNextPDU();
else if(!inThread.isValidPDU()){
inThread.printNextPDU();
receive=false;
try {
outThread.stop();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
};
thread.start();
//Takes input from user and sends to chat-server.
while(thread.isAlive()){
if(scanner.hasNextLine()){
message = scanner.nextLine();
if(!message.equals("/quit")&&chat&&thread.isAlive())
outThread.sendPDU(new PDU_MESS(message,clientName));
else if(chat&&thread.isAlive()){
outThread.stop();
chat=false;
}
}
}
//Waiting for the threads to close
System.exit(0);
socket.close();
}
/**
* @param args Identity,Server Type,Host Address,Host Port.
* @throws IOException if the arguments are invalid.
*/
public static void main(String[] args) throws IOException, InterruptedException {
if(args.length==4){
new ChatClient(args[0],args[1],args[2],new Integer(args[3]));
}
else
throw new IOException("Invalid number of arguments" +
",(Identity,ServerType,HostAddress,HostPort)");
}
}