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 package ffx.ui.commands;
39
40 import java.io.ObjectInputStream;
41 import java.io.ObjectOutputStream;
42 import java.net.InetAddress;
43 import java.net.InetSocketAddress;
44 import java.net.ServerSocket;
45 import java.net.Socket;
46 import java.util.ListIterator;
47 import java.util.Vector;
48 import java.util.logging.Logger;
49
50
51
52
53
54
55 public class FFXServer implements Runnable {
56
57 private static final Logger logger = Logger.getLogger(FFXServer.class.getName());
58 private static SimulationMessage closing = new SimulationMessage(SimulationMessage.CLOSING);
59 private ServerSocket server;
60 private int serverPort = 2000;
61 private int serverTimeout = 100;
62 private Thread thread;
63 private int sleepTime = 1;
64 private boolean init = true;
65 private int cycle = 0;
66 private boolean shutdown = false;
67 private boolean request = false;
68 private Vector<Socket> clients = new Vector<Socket>();
69 private Vector<ObjectOutputStream> outputs = new Vector<ObjectOutputStream>();
70 private Vector<ObjectInputStream> inputs = new Vector<ObjectInputStream>();
71 private SimulationDefinition system = null;
72 private SimulationUpdate update = null;
73
74
75
76
77
78
79 public FFXServer(SimulationDefinition s) {
80 system = s;
81 }
82
83
84
85
86
87
88 public boolean isAlive() {
89 if (thread == null) {
90 return false;
91 } else if (thread.isAlive()) {
92 return true;
93 } else {
94 return false;
95 }
96 }
97
98
99
100
101
102
103 public void loadUpdate(SimulationUpdate u) {
104 update = u;
105 }
106
107
108
109
110
111
112 public boolean needUpdate() {
113 if (clients.isEmpty()) {
114 sleepTime = 100;
115 return false;
116 }
117 if (request != true) {
118 return false;
119 }
120 sleepTime = 1;
121 return true;
122 }
123
124
125 public void run() {
126 startServer();
127 while (!shutdown) {
128 accept();
129 send();
130 try {
131 Thread.sleep(sleepTime);
132 } catch (Exception e) {
133
134 logger.severe("Server: thread sleep interrupted\n");
135 }
136 if (init) {
137 cycle++;
138 if (cycle >= 10) {
139 init = false;
140 serverTimeout = 1;
141 }
142 }
143 }
144 accept();
145 send();
146 closeServer();
147 }
148
149
150 public void setUpdated() {
151 request = false;
152 }
153
154
155 public void start() {
156 if (thread == null || !thread.isAlive()) {
157 thread = new Thread(this);
158 thread.setPriority(Thread.MAX_PRIORITY);
159 thread.start();
160 }
161 }
162
163
164 public void stop() {
165 shutdown = true;
166 }
167
168 private void accept() {
169 Socket client = null;
170 ObjectOutputStream oout = null;
171 ObjectInputStream oin = null;
172 if (server != null) {
173 try {
174 client = server.accept();
175 if (client != null && client.isConnected()) {
176 client.setTcpNoDelay(true);
177 clients.add(client);
178 oout = new ObjectOutputStream(client.getOutputStream());
179 outputs.add(oout);
180 oin = new ObjectInputStream(client.getInputStream());
181 inputs.add(oin);
182 Logger.getLogger("ffx").info("Client connected\n" + client);
183 }
184 } catch (Exception e) {
185 if (client != null) {
186 clients.remove(client);
187 }
188 if (oout != null) {
189 outputs.remove(oout);
190 }
191 if (oin != null) {
192 inputs.remove(oin);
193 }
194 }
195 }
196 }
197
198 private void closeClient(int index) {
199 Socket client = clients.get(index);
200 ObjectOutputStream oout = outputs.get(index);
201 ObjectInputStream oin = inputs.get(index);
202 try {
203 oout.reset();
204 oout.writeObject(closing);
205 oout.flush();
206 } catch (Exception e) {
207 try {
208 outputs.remove(index);
209 inputs.remove(index);
210 clients.remove(index);
211 if (oout != null) {
212 oout.close();
213 }
214 if (oin != null) {
215 oin.close();
216 }
217 if (client != null) {
218 client.close();
219 }
220 } catch (Exception ignored) {
221 }
222 }
223 }
224
225 private void closeServer() {
226 for (int i = 0; i < clients.size(); i++) {
227 lastUpdate(i);
228 }
229 while (!clients.isEmpty()) {
230 closeClient(0);
231 try {
232 synchronized (this) {
233 wait(10);
234 }
235 } catch (Exception e) {
236 Logger.getLogger("ffx").severe(e.toString());
237 }
238 }
239 try {
240 if (server != null) {
241 server.close();
242 server = null;
243 }
244 } catch (Exception ignored) {
245 }
246 }
247
248 private void lastUpdate(int index) {
249 try {
250 ObjectOutputStream oout = outputs.get(index);
251 Socket client = clients.get(index);
252 if (client != null && client.isConnected() && oout != null) {
253 SimulationMessage last = new SimulationMessage(SimulationMessage.SYSTEM);
254 if (system != null) {
255 oout.reset();
256 oout.writeObject(last);
257 oout.writeObject(system);
258 oout.flush();
259 }
260 if (update != null) {
261 oout.reset();
262 last.setMessage(SimulationMessage.UPDATE);
263 oout.writeObject(last);
264 oout.writeObject(update);
265 oout.flush();
266 }
267 last.setMessage(SimulationMessage.CLOSING);
268 oout.reset();
269 oout.writeObject(last);
270 oout.flush();
271 }
272 } catch (Exception e) {
273 logger.severe("" + e);
274 }
275 }
276
277 private void send() {
278 if (system == null) {
279 return;
280 }
281 if (clients.isEmpty()) {
282 return;
283 }
284 ObjectOutputStream oout;
285 ObjectInputStream oin;
286 Socket client;
287 ListIterator<ObjectOutputStream> lout;
288 ListIterator<ObjectInputStream> lin;
289 ListIterator<Socket> lclient;
290 Vector<Socket> closed = new Vector<Socket>();
291 for (lout = outputs.listIterator(),
292 lin = inputs.listIterator(),
293 lclient = clients.listIterator();
294 lout.hasNext(); ) {
295 oout = lout.next();
296 oin = lin.next();
297 client = lclient.next();
298 if (!client.isConnected() || client.isClosed()) {
299 closed.add(client);
300 } else {
301 try {
302 SimulationMessage message = null;
303 while (oin != null && client.getInputStream().available() > 0) {
304 Object o = oin.readObject();
305 if (o instanceof SimulationMessage) {
306 message = (SimulationMessage) o;
307 if (message.getMessage() == SimulationMessage.CLOSING) {
308 closed.add(client);
309 message = null;
310 break;
311 }
312 }
313 }
314 if (message != null) {
315 if (message.getMessage() == SimulationMessage.SYSTEM) {
316 synchronized (system) {
317 oout.reset();
318 oout.writeObject(message);
319 oout.writeObject(system);
320 oout.flush();
321 }
322 } else if (message.getMessage() == SimulationMessage.UPDATE) {
323 request = true;
324 if (update != null && update.isNewer(message)) {
325 synchronized (update) {
326
327 oout.reset();
328 oout.writeObject(message);
329 oout.writeObject(update);
330 oout.flush();
331 }
332 }
333 }
334 }
335 } catch (Exception e) {
336 closed.add(client);
337 }
338 }
339 }
340 for (Socket s : closed) {
341 int index = closed.indexOf(s);
342 closeClient(index);
343 }
344 }
345
346 private void startServer() {
347 try {
348 server = new ServerSocket();
349 server.setSoTimeout(serverTimeout);
350 server.setReuseAddress(true);
351 server.bind(new InetSocketAddress(InetAddress.getLocalHost(), serverPort));
352 } catch (Exception e) {
353 try {
354 server.bind(new InetSocketAddress(InetAddress.getByName(null), serverPort));
355 } catch (Exception ex) {
356 Logger.getLogger("ffx").severe("SERVER -- Could not start\n" + e);
357 return;
358 }
359 }
360 Logger.getLogger("ffx").info("FFX Server Address: " + server.getLocalSocketAddress());
361
362
363 }
364 }