-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathServer.java
276 lines (239 loc) · 8.75 KB
/
Server.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
import java.net.*;
/**
* <p>Materialien zu den zentralen
* Abiturpruefungen im Fach Informatik ab 2012 in
* Nordrhein-Westfalen.</p>
* <p>Klasse Server</p>
* Ein Server ist ein vereinfachter ServerSocket, der zusätzliche Funktionen hat.<br>
* Es können beliebig viele Kontakte mit Clientverbindungen aufgebaut werden.<br>
* Der Dialog mit den Clients wird nebenläufig realisiert.
* <p>NW-Arbeitsgruppe: Materialentwicklung zum Zentralabitur
* im Fach Informatik</p>
*
* @version 2011-12-12
*/
public abstract class Server
{
// Objekte
private ServerSocket serverSocket;
private List verbindungen;
private ServerSchleife schleife;
// Attribute
private int zPort;
/**
Verbindung des Servers mit einem Client.<br>
Kann nebenläaeufig die empfangenen Nachrichten bearbeiten.
@author Horst Hildebrecht
@version 1.0
*/
private class ServerConnection extends Connection
{
// Objekte
Server server;
//Connection sConnection;
/*
Die ServerVerbindung wurde inialisiert.
@param pSocket Socket, der die Verbindung beschreibt
@param pServer Server, den die ServerVerbindung kennen lernt
*/
public ServerConnection(Socket pSocket, Server pServer)
{
super(pSocket);
server = pServer;
}
/**
Solange der Client Nachrichten sendete, wurden diese empfangen und an die Server weitergereicht.<br>
Abgebrochene Verbindungen wurden erkannt.
*/
public void run()
{
String lNachricht;
while (!this.isClosed())
{
lNachricht = this.receive();
if (lNachricht == null)
{
if (!this.isClosed())
{
server.closeConnection(this.getRemoteIP(), this.getRemotePort());
}
}
else
server.processMessage(this.getRemoteIP(), this.getRemotePort(), lNachricht);
}
}
}
private class ServerSchleife extends Thread
{
private Server server;
public ServerSchleife(Server pServer)
{
server = pServer;
}
public void run()
{
while (true) // ewige Schleife
{
try
{
Socket lClientSocket = server.serverSocket.accept();
ServerConnection lNeueSerververbindung = new ServerConnection(lClientSocket, server);
// Der Client laeuft in einem eigenen Thread, damit mehrere Clients gleichzeitig
// auf den Server zugreifen koennen.
server.ergaenzeVerbindung(lNeueSerververbindung);
lNeueSerververbindung.start();
}
catch (Exception pFehler)
{
System.err.println("Fehler beim Erwarten einer Verbindung in Server: " + pFehler);
}
}
}
}
/**
Der Server ist initialisiert.
@param pPortNr Portnummer des Sockets
*/
public Server(int pPortNr)
{
try
{
//Socket oeffnen
serverSocket = new ServerSocket(pPortNr);
zPort = pPortNr;
verbindungen = new List();
schleife = new ServerSchleife(this);
schleife.start();
}
catch (Exception pFehler)
{
System.err.println("Fehler beim \u00D6ffnen der Server: " + pFehler);
}
}
public String toString()
{
return "Server von ServerSocket: " + serverSocket;
}
private void ergaenzeVerbindung(ServerConnection pVerbindung)
{
verbindungen.append(pVerbindung);
this.processNewConnection(pVerbindung.getRemoteIP(), pVerbindung.getRemotePort());
}
/**
Liefert die Serververbindung der angegebenen IP mit dem angegebenen Port, null falls nicht vorhanden.
@param pClientIP IP-Nummer des Clients der gesuchten Verbindung
@param pClientPort Port-Nummer des Clients der gesuchten Verbindung
*/
private ServerConnection SerververbindungVonIPUndPort(String pClientIP, int pClientPort)
{
ServerConnection lSerververbindung;
verbindungen.toFirst();
while (verbindungen.hasAccess())
{
lSerververbindung = (ServerConnection) verbindungen.getObject();
if (lSerververbindung.getRemoteIP().equals(pClientIP) && lSerververbindung.getRemotePort() == pClientPort)
return lSerververbindung;
verbindungen.next();
}
return null; // IP nicht gefunden
}
/**
Eine Nachricht wurde an einen Client geschickt.
@param pClientIP IP-Nummer des Empfängers
@param pClientPort Port-Nummer des Empfängers
@param pMessage die verschickte Nachricht
*/
public void send(String pClientIP, int pClientPort, String pMessage)
{
ServerConnection lSerververbindung = this.SerververbindungVonIPUndPort(pClientIP, pClientPort);
if (lSerververbindung != null)
lSerververbindung.send(pMessage);
else
System.err.println("Fehler beim Senden: IP " + pClientIP + " mit Port " + pClientPort + " nicht vorhanden.");
}
/**
Eine Nachricht wurde an alle verbundenen Clients geschickt.
@param pMessage die verschickte Nachricht
*/
public void sendToAll(String pMessage)
{
ServerConnection lSerververbindung;
verbindungen.toFirst();
while (verbindungen.hasAccess())
{
lSerververbindung = (ServerConnection) verbindungen.getObject();
lSerververbindung.send(pMessage);
verbindungen.next();
}
}
/**
Die Verbindung mit der angegebenen IP und dem angegebenen Port wurde geschlossen.<br>
@param pClientIP IP-Nummer des Clients der zu beendenden Verbindung
@param pClientPort Port-Nummer des Clients der zu beendenden Verbindung
*/
public void closeConnection (String pClientIP, int pClientPort)
{
ServerConnection lSerververbindung = this.SerververbindungVonIPUndPort(pClientIP, pClientPort);
if (lSerververbindung != null)
{ this.processClosedConnection(pClientIP, pClientPort);
lSerververbindung.close();
this.loescheVerbindung(lSerververbindung);
}
else
System.err.println("Fehler beim Schlie\u00DFen der Verbindung: IP " + pClientIP + " mit Port " + pClientPort + " nicht vorhanden.");
}
/**
Eine Verbindung wurde aus der Empfängerliste gelöscht.
@param pVerbindung die zu löschende Verbindung
*/
private void loescheVerbindung(ServerConnection pVerbindung)
{
verbindungen.toFirst();
while (verbindungen.hasAccess())
{
ServerConnection lClient = (ServerConnection) verbindungen.getObject();
if (lClient == pVerbindung)
verbindungen.remove();
verbindungen.next();
}
}
/**
Ein neuer Client hat sich angemeldet.<br>
Diese leere Methode kann in einer Unterklasse realisiert werden (Begrüßung).
@param pClientIP IP-Nummer des Clients, der neu angemeldet ist
@param pClientPort Port-Nummer des Clients, der neu angemeldet ist
*/
public void processNewConnection(String pClientIP, int pClientPort)
{}
/**
Eine Nachricht von einem Client wurde bearbeitet.<br>
Diese leere Methode sollte in Unterklassen überschrieben werden.
@param pClientIP IP-Nummer des Clients, der die Nachricht geschickt hat
@param pClientPort Port-Nummer des Clients, der die Nachricht geschickt hat
@param pMessage Die empfangene Nachricht, die bearbeitet werden soll
*/
public void processMessage(String pClientIP, int pClientPort, String pMessage)
{}
/**
Die Verbindung mit einem Client wurde beendet oder verloren.<br>
Diese leere Methode kann in einer Unterklasse realisiert werden.
@param pClientIP IP-Nummer des Clients, mit dem die Verbindung beendet wurde
@param pClientPort Port-Nummer des Clients, mit dem die Verbindung beendet wurde
*/
public void processClosedConnection(String pClientIP, int pClientPort)
{}
/**
Der Server wurde geschlossen.
*/
public void close()
{
try
{
serverSocket.close(); serverSocket = null;
}
catch (Exception pFehler)
{
System.err.println("Fehler beim Schlie\u00DFen des Servers: " + pFehler);
}
}
}