-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSuperSocketMaster.java
executable file
·414 lines (409 loc) · 15 KB
/
SuperSocketMaster.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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.AWTEventMulticaster;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.NetworkInterface;
import java.net.Inet4Address;
import java.net.SocketException;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.util.Vector;
import java.util.Enumeration;
/**
* <h1>SuperSocketMaster</h1>
* This class gives Java students the ability to quickly open a Java network socket<p>
* They can then send outgoing text over the socket<p>
* They can recieve incoming text over the socket<p>
* Incoming text triggers an ActionEvent<p>
* This class is meant to be used in Java Swing/AWT programs
* @author Alfred Cadawas
* @version 2.0
* @since 2016-04-21
*/
public class SuperSocketMaster{
// Properties
private int intPort = 1337;
private String strServerIP = null;
private String strIncomingText = null;
private SocketConnection soccon = null;
transient ActionListener actionListener = null;
// Methods
/**
* Sends text over the open socket<p>
* If the socket is not open, the text goes nowhere<p>
* You can use this to check to see of the socket is still open
*
* @param strText Text you want to send over the network socket
* @return Returns true if data was successfully sent over the network
*/
public boolean sendText(String strText){
if(soccon != null){
return soccon.sendText(strText);
}
return false;
}
/**
* Reads the text that was recieved from the open socket<p>
* Should only be called after and ActionEvent is triggered
*
* @return Returns recieved text from the socket or an empty string
*/
public String readText(){
if(soccon != null){
return strIncomingText;
}else{
return "";
}
}
/**
* Disconnects all open sockets<p>
* Servers will disconnect all clients before closing the server socket<p>
* Clients will disconnect their socket connection to the server
*/
public void disconnect(){
if(soccon != null){
soccon.closeConnection();
soccon = null;
}
}
/**
* Gets the IP Address of the computer<p>
* Should grab the Ethernet IP first if both Wifi and Ethernet are connected
*
* @return Returns computer's IP address
*/
public String getMyAddress(){
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface) networkInterfaces.nextElement();
Enumeration<InetAddress> niAddresses = networkInterface.getInetAddresses();
while(niAddresses.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) niAddresses.nextElement();
if (!inetAddress.isLinkLocalAddress() && !inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException e) {
}
return "127.0.0.1";
}
/**
* Gets the Hostname of the computer
*
* @return Returns computer's Hostname
*/
public String getMyHostname(){
try{
return InetAddress.getLocalHost().getHostName();
}catch(UnknownHostException e){
return "localhost";
}
}
/**
* Opens a socket connection<p>
* Server - Opens a server socket and waits for clients to connect<p>
* Client - Opens a socket and connects to the server<p>
* Once connected, both start a thread to listen for incoming clients or incoming text
*
* @return Returns true if socket connection was successfull
*/
public boolean connect(){
// First check to see if you can make a socket connection
soccon = new SocketConnection(strServerIP, intPort, this);
if(soccon.openConnection()){
return true;
}else{
soccon = null;
return false;
}
}
private synchronized void addActionListener(ActionListener listener) {
actionListener = AWTEventMulticaster.add(actionListener, listener);
}
private synchronized void removeActionListener(ActionListener listener) {
actionListener = AWTEventMulticaster.remove(actionListener, listener);
}
private void postActionEvent() {
// when event occurs which causes "action" semantic
ActionListener listener = actionListener;
if (listener != null) {
listener.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,"Network Message"));
}
}
// Constructor
/**
* Server Mode SuperSocketMaster Constructor<p>
*
* @param intPort TCP Port you want to use for your connection
* @param listener Swing/AWT program's ActionListener. Usually "this"
*/
public SuperSocketMaster(int intPort, ActionListener listener){
this.addActionListener(listener);
this.intPort = intPort;
}
/**
* Client Mode SuperSocketMaster Constructor<p>
*
* @param strServerIP Hostname or IP address of the server you want to connect to
* @param intPort TCP Port you want to use for your connection
* @param listener Swing/AWT program's ActionListener. Usually "this"
*/
public SuperSocketMaster(String strServerIP, int intPort, ActionListener listener){
this.addActionListener(listener);
this.intPort = intPort;
this.strServerIP = strServerIP;
}
/********************************************************************
* SocketConnection Class
* Creates a socket connection in either server mode or client
* Server opens a server socket and listens for incomming connections
* If a connection is made, make an appropriate client object
* and starts listening for data
* Client opens a socket and starts listening for data
* *****************************************************************/
private class SocketConnection implements Runnable{
SuperSocketMaster parentssm = null;
int intPort = 1337;
String strServerIP = null;
String strIncomingText = "";
ServerSocket serverSocketObject = null;
Socket socketObject = null;
PrintWriter outBuffer = null;
BufferedReader inBuffer = null;
String strMyIP;
String strMyHostname;
Vector<ClientConnection> clientconnections = new Vector<ClientConnection>();
boolean blnListenForClients = true;
public boolean sendText(String strText) {
if (strServerIP == null || strServerIP.equals("")) {
// Server mode sending text needs to send to all clients
// It therefore goes through the vector
// and uses each object's sendText method.
////System.out.println("Sending message to all "+portconnections.size()+" clients: "+strText);
for (int intCounter = 0; intCounter < clientconnections.size(); intCounter++) {
clientconnections.get(intCounter).sendText(strText);
}
return true;
} else {
// Client mode is much easier.
////System.out.println("Sending message: "+strText);
// First check if connecion is down
if(socketObject != null){
if(outBuffer.checkError()){
closeConnection();
return false;
}else{
outBuffer.println(strText);
return true;
}
}
return false;
}
}
// This might be called buy two areas simultaneously!
// Might be called by the disconnecting while loop in the run method
// Might be called by the disconnect method.
public void removeClient(ClientConnection clientConnection){
if(clientConnection.socketObject != null){
System.out.println("Trying to close server connection to client");
try{
// Since two methods might be running this code simultaneously
// Some of the objects might be null
// So catch the null pointer exception
// the first method that accesses this should close everything correctly
try{
clientConnection.socketObject.shutdownInput();
clientConnection.socketObject.shutdownOutput();
clientConnection.socketObject.close();
clientConnection.outBuffer.close();
clientConnection.inBuffer.close();
clientConnection.socketObject = null;
clientConnection.inBuffer = null;
clientConnection.outBuffer = null;
clientConnection.strIncomingText = null;
System.out.println("Done closing server connection to client");
clientconnections.remove(clientConnection);
clientConnection = null;
System.out.println("Server removed a client connection. Current Size: "+clientconnections.size());
}catch(NullPointerException e){
}
}catch(IOException e){
}
}
}
public void run(){
if(strServerIP == null || strServerIP.equals("")){
// Server
// while loop to listen for incoming clients
// When a client connects, create a socket object
// Add that socket object to a vector
// Spawn a thread with that socket object
// One thread for each client
while (blnListenForClients) {
try {
socketObject = serverSocketObject.accept();
ClientConnection singleconnection = new ClientConnection(this.parentssm, this.socketObject, this);
clientconnections.addElement(singleconnection);
Thread t1 = new Thread(singleconnection);
t1.start();
System.out.println("Server accepted a client connection: Current Size: "+clientconnections.size());
} catch (IOException e) {
blnListenForClients = false;
}
}
}else{
// Client
// Already connected to a server and have a socket object
// while loop to listen for incoming data
while (strIncomingText != null) {
try {
strIncomingText = inBuffer.readLine();
if(strIncomingText != null){
this.parentssm.strIncomingText = strIncomingText;
this.parentssm.postActionEvent();
}
} catch (IOException e) {
}
}
System.out.println("reading while loop done");
// CADAWAS
closeConnection();
}
}
public void closeConnection(){
// If server, kill all client sockets then close the serversocket
if(strServerIP == null || strServerIP.equals("")){
blnListenForClients = false;
while(clientconnections.size() > 0){
removeClient(clientconnections.get(0));
//System.out.println("Trying to remove all clients");
}
try{
serverSocketObject.close();
}catch(IOException e){
}
serverSocketObject = null;
clientconnections = null;
}else{
// If client, just kill the socket
// This might be called buy two areas simultaneously!
// Might be called by the disconnecting while loop in the run method
// Might be called by the disconnect method.
if(socketObject != null){
System.out.println("Trying to close the client conneccion");
try{
// Since two methods might be running this code simultaneously
// Some of the objects might be null
// So catch the null pointer exception
// the first method that accesses this should close everything correctly
try{
socketObject.shutdownInput();
socketObject.shutdownOutput();
socketObject.close();
outBuffer.close();
inBuffer.close();
socketObject = null;
inBuffer = null;
outBuffer = null;
strIncomingText = null;
System.out.println("Done closing client connection");
}catch(NullPointerException e){
}
}catch(IOException e){
}
}
}
}
public boolean openConnection(){
if(strServerIP == null || strServerIP.equals("")){
// Server style connection.
// Open Port
// Create a serversocket object
try {
serverSocketObject = new ServerSocket(intPort);
} catch (IOException e) {
return false;
}
Thread t1 = new Thread(this);
t1.start();
System.out.println("Server port opened. Listening to incoming client connections");
return true;
}else{
// Client style connection.
// Open port
// Create a socket object
try {
socketObject = new Socket(strServerIP, intPort);
outBuffer = new PrintWriter(socketObject.getOutputStream(), true);
inBuffer = new BufferedReader(new InputStreamReader(socketObject.getInputStream()));
} catch (IOException e) {
return false;
}
Thread t1 = new Thread(this);
t1.start();
System.out.println("Client connected to server. Listening for incoming data");
return true;
}
}
public SocketConnection(String strServerIP, int intPort, SuperSocketMaster parentssm){
this.strServerIP = strServerIP;
this.intPort = intPort;
this.parentssm = parentssm;
}
}
private class ClientConnection implements Runnable{
SuperSocketMaster parentssm = null;
SocketConnection socketConnection = null;
String strIncomingText = "";
Socket socketObject = null;
PrintWriter outBuffer = null;
BufferedReader inBuffer = null;
public void run(){
try {
inBuffer = new BufferedReader(new InputStreamReader(socketObject.getInputStream()));
outBuffer = new PrintWriter(socketObject.getOutputStream(), true);
} catch (IOException e) {
}
while (strIncomingText != null) {
try {
strIncomingText = inBuffer.readLine();
if(strIncomingText != null){
// Send to all other clients except for this recieving one
for (int intCounter = 0; intCounter < socketConnection.clientconnections.size(); intCounter++) {
if(socketConnection.clientconnections.get(intCounter) != this){
socketConnection.clientconnections.get(intCounter).sendText(strIncomingText);
}
}
// Then set text
this.parentssm.strIncomingText = strIncomingText;
this.parentssm.postActionEvent();
}
} catch (IOException e) {
}
}
System.out.println("reading while loop done");
socketConnection.removeClient(this);
}
public boolean sendText(String strText) {
if(outBuffer.checkError()){
socketConnection.removeClient(this);
return false;
}else{
outBuffer.println(strText);
return true;
}
}
public ClientConnection(SuperSocketMaster parentssm, Socket socketObject, SocketConnection socketConnection){
this.socketConnection = socketConnection;
this.socketObject = socketObject;
this.parentssm = parentssm;
}
}
}