|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 import java.net.*; |
|
20 import java.io.*; |
|
21 |
|
22 public class EchoServer extends Thread{ |
|
23 |
|
24 // Constants |
|
25 |
|
26 // Commands available |
|
27 private final String iCommandShutdown = "Shutdown."; |
|
28 private final String iCommandShutdownNow = "ShutdownNow."; |
|
29 private final String iCommandStopReturning = "StopReturning."; |
|
30 private final String iCommandStartReturning = "StartReturning."; |
|
31 private final String iCommandSleep = "sleep="; |
|
32 private final String iCommandSendBufferSize = "sendbufsize="; |
|
33 private final String iCommandReceiveBufferSize = "recvbufsize="; |
|
34 |
|
35 private final int iBufferSize = 256; |
|
36 |
|
37 // Static variables |
|
38 private static final int sDefaultTcpPort = 10007; |
|
39 private static int sPort; |
|
40 |
|
41 // Member variables |
|
42 private Socket iClientSocket; |
|
43 private boolean iUdpSocket; |
|
44 private int iUdpPort; |
|
45 |
|
46 private String iClientHost; |
|
47 private int iClientPort; |
|
48 |
|
49 private int iSendBufferLength = 0; |
|
50 private int iReceiveBufferLength = 0; |
|
51 |
|
52 private boolean iEchoData = true; |
|
53 private boolean iPortSet = false; |
|
54 |
|
55 public static void main(String[] aArgs) throws IOException{ |
|
56 |
|
57 ServerSocket lServerSocket = null; |
|
58 sPort = sDefaultTcpPort; |
|
59 boolean lUdpSocket = false; |
|
60 if (aArgs.length > 0){ |
|
61 try{ |
|
62 sPort = Integer.parseInt(aArgs[0]); |
|
63 } |
|
64 catch(NumberFormatException nfe){ |
|
65 System.out.println("Usage:\n\tjava EchoServer [port [protocol]]\n\tIf port is not specified, port: " + sDefaultTcpPort + " will be used\n\tProtocol is TCP or UDP if not specified or incorrect TCP is default"); |
|
66 System.exit(1); |
|
67 } |
|
68 if (aArgs.length > 1){ |
|
69 if (aArgs[1].equalsIgnoreCase("UDP")){ |
|
70 lUdpSocket = true; |
|
71 } |
|
72 } |
|
73 } |
|
74 // UDP Version |
|
75 if (lUdpSocket){ |
|
76 System.out.println("Connection Socket Created for UDP connection on port: " + sPort); |
|
77 while (true){ |
|
78 try{ |
|
79 java.lang.Thread.sleep(1000); |
|
80 } |
|
81 catch(java.lang.InterruptedException ie){ |
|
82 System.err.println("Sleep inturrupted."); |
|
83 } |
|
84 System.out.println("Waiting for Connection"); |
|
85 EchoServer lEchoServer = new EchoServer(sPort); |
|
86 lEchoServer.handleUDP(); |
|
87 } |
|
88 } |
|
89 |
|
90 // TCP version |
|
91 else{ |
|
92 |
|
93 try{ |
|
94 lServerSocket = new ServerSocket(sPort); |
|
95 System.out.println("Connection Socket Created for TCP connection on port: " + sPort); |
|
96 |
|
97 try{ |
|
98 while (true){ |
|
99 System.out.println("Waiting for Connection"); |
|
100 new EchoServer(lServerSocket.accept()); |
|
101 } |
|
102 } |
|
103 catch(IOException e){ |
|
104 System.err.println("Accept failed."); |
|
105 System.exit(1); |
|
106 } |
|
107 } |
|
108 catch(IOException e){ |
|
109 System.err.println("Could not listen on port: " + sPort + "."); |
|
110 System.exit(1); |
|
111 } |
|
112 finally{ |
|
113 try{ |
|
114 lServerSocket.close(); |
|
115 } |
|
116 catch(IOException e){ |
|
117 System.err.println("Could not close port: " + sPort + "."); |
|
118 System.exit(1); |
|
119 } |
|
120 } |
|
121 } |
|
122 } |
|
123 |
|
124 private EchoServer(Socket aClientSoc){ |
|
125 |
|
126 iClientSocket = aClientSoc; |
|
127 iUdpSocket = false; |
|
128 |
|
129 InetAddress lIpAddress = iClientSocket.getInetAddress(); |
|
130 iClientHost = lIpAddress.getHostAddress(); |
|
131 System.out.println("Accepted from IP Address: " + iClientHost); |
|
132 |
|
133 start(); |
|
134 } |
|
135 |
|
136 private EchoServer(int aPort){ |
|
137 |
|
138 iUdpSocket = true; |
|
139 iUdpPort = aPort; |
|
140 } |
|
141 |
|
142 // returns true if iClientPort successfully parsed |
|
143 private boolean parsePort(String aMessage){ |
|
144 |
|
145 // If the text is formatted like this: |
|
146 // [2024] |
|
147 // parse the client port so that connection back to this preference is possible |
|
148 int lFirstIndex = aMessage.indexOf('['); |
|
149 int lSecondIndex = aMessage.indexOf(']'); |
|
150 |
|
151 if ( (lFirstIndex == 0) && (lSecondIndex > 1) ){ |
|
152 |
|
153 String lPortString = aMessage.substring(1, lSecondIndex); |
|
154 int lPort = 0; |
|
155 |
|
156 try{ |
|
157 lPort = Integer.parseInt(lPortString); |
|
158 } |
|
159 catch(NumberFormatException nfe){ |
|
160 System.out.println("Failed to parse port to integer"); |
|
161 return false; |
|
162 } |
|
163 |
|
164 iClientPort = lPort; |
|
165 iPortSet = true; |
|
166 return true; |
|
167 } |
|
168 return false; |
|
169 } |
|
170 |
|
171 // returns true if integer successfully parsed |
|
172 private int parseIntCommand(String aMessage, String aCommandName){ |
|
173 |
|
174 // If the text is formatted like this: |
|
175 // command=x |
|
176 // parse the integer x |
|
177 int lResult = -1; |
|
178 |
|
179 if (aMessage.startsWith(aCommandName)){ |
|
180 |
|
181 int lDotIndex = aMessage.indexOf('.'); |
|
182 |
|
183 if (lDotIndex < 0){ |
|
184 lDotIndex = aMessage.length(); |
|
185 } |
|
186 |
|
187 String lResultString = aMessage.substring(aCommandName.length(), lDotIndex); |
|
188 |
|
189 try{ |
|
190 lResult = Integer.parseInt(lResultString); |
|
191 } |
|
192 catch(NumberFormatException nfe){ |
|
193 System.out.println("Failed to parse integer"); |
|
194 } |
|
195 } |
|
196 return lResult; |
|
197 } |
|
198 |
|
199 // TCP Handling |
|
200 public void run(){ |
|
201 |
|
202 System.out.println("New TCP Communication Thread Started"); |
|
203 try{ |
|
204 |
|
205 PrintWriter lOut = null; |
|
206 Socket lClientSocketConn = null; |
|
207 BufferedReader lIn = new BufferedReader(new InputStreamReader(iClientSocket.getInputStream())); |
|
208 String lInputLine; |
|
209 boolean lExit = false; |
|
210 int lTempResult = -1; |
|
211 |
|
212 while (lExit == false){ |
|
213 |
|
214 char lDataReceived[] = new char[iBufferSize]; |
|
215 |
|
216 int lLengthOfData = lIn.read(lDataReceived); |
|
217 |
|
218 if (lLengthOfData <= 0){ |
|
219 lExit = true; |
|
220 continue; |
|
221 } |
|
222 |
|
223 lInputLine = new String(lDataReceived, 0, lLengthOfData); |
|
224 |
|
225 System.out.println("Server: " + lInputLine); |
|
226 |
|
227 lTempResult = parseIntCommand(lInputLine, iCommandReceiveBufferSize); |
|
228 if (lTempResult != -1){ // Message parsed |
|
229 if (lTempResult > 0){ |
|
230 iReceiveBufferLength = lTempResult; |
|
231 iClientSocket.setReceiveBufferSize(iReceiveBufferLength); |
|
232 System.out.println("RECEIVE BUFFER LENGTH SET TO " + iClientSocket.getReceiveBufferSize()); |
|
233 } |
|
234 else{ |
|
235 System.out.println("INVALID RECEIVE BUFFER LENGTH: " + iReceiveBufferLength); |
|
236 } |
|
237 } |
|
238 |
|
239 lTempResult = parseIntCommand(lInputLine, iCommandSendBufferSize); |
|
240 if (lTempResult != -1){ // Message parsed |
|
241 if (lTempResult > 0){ |
|
242 iSendBufferLength = lTempResult; |
|
243 } |
|
244 else{ |
|
245 System.out.println("INVALID SEND BUFFER LENGTH: " + lTempResult); |
|
246 } |
|
247 } |
|
248 if (iSendBufferLength > 0){ |
|
249 lClientSocketConn.setSendBufferSize(iSendBufferLength); |
|
250 System.out.println("SEND BUFFER LENGTH SET TO " + lClientSocketConn.getSendBufferSize()); |
|
251 } |
|
252 |
|
253 if (parsePort(lInputLine)){ |
|
254 try{ |
|
255 lClientSocketConn = new Socket(iClientHost, iClientPort); |
|
256 lOut = new PrintWriter(lClientSocketConn.getOutputStream(), true); |
|
257 } |
|
258 catch(UnknownHostException e){ |
|
259 System.err.println("Don't know about host: " + iClientHost); |
|
260 lExit = true; |
|
261 continue; |
|
262 } |
|
263 catch(IOException e){ |
|
264 System.err.println("Couldn't get I/O for the connection to: " + iClientHost); |
|
265 lExit = true; |
|
266 continue; |
|
267 } |
|
268 } |
|
269 |
|
270 if (lInputLine.startsWith(iCommandStartReturning)){ |
|
271 System.out.println("ECHOING ACTIVATED"); |
|
272 iEchoData = true; |
|
273 } |
|
274 |
|
275 if (lInputLine.startsWith(iCommandShutdownNow)){ |
|
276 System.out.println("SHUTTING DOWN"); |
|
277 break; |
|
278 } |
|
279 |
|
280 if ( (lOut != null) && iEchoData ){ |
|
281 System.out.println("Echo to host: " + iClientHost + ":" + iClientPort); |
|
282 lOut.print(lInputLine); |
|
283 lOut.flush(); |
|
284 } |
|
285 |
|
286 if (lInputLine.startsWith(iCommandShutdown)){ |
|
287 System.out.println("SHUTTING DOWN"); |
|
288 break; |
|
289 } |
|
290 |
|
291 if (lInputLine.startsWith(iCommandStopReturning)){ |
|
292 System.out.println("ECHOING DEACTIVATED"); |
|
293 iEchoData = false; |
|
294 } |
|
295 |
|
296 int lSleepLength = parseIntCommand(lInputLine, iCommandSleep); |
|
297 if (lSleepLength != -1){ // Message parsed |
|
298 if (lSleepLength > 0){ |
|
299 System.out.println("SLEEPING FOR " + lSleepLength + " MILLISECONDS"); |
|
300 try{ |
|
301 java.lang.Thread.sleep(lSleepLength); |
|
302 } |
|
303 catch(java.lang.InterruptedException ie){ |
|
304 System.err.println("Sleep inturrupted."); |
|
305 } |
|
306 } |
|
307 else{ |
|
308 System.out.println("INVALID SLEEP LENGTH: " + lSleepLength + " MILLISECONDS"); |
|
309 } |
|
310 } |
|
311 } |
|
312 |
|
313 if (lOut != null){ |
|
314 lOut.close(); |
|
315 lClientSocketConn.close(); |
|
316 } |
|
317 |
|
318 lIn.close(); |
|
319 iClientSocket.close(); |
|
320 System.out.println("Communication Thread Ended"); |
|
321 } |
|
322 catch(IOException e){ |
|
323 System.err.println("Problem with Communication Server"); |
|
324 } |
|
325 } |
|
326 |
|
327 // UDP Handling |
|
328 public void handleUDP(){ |
|
329 |
|
330 DatagramSocket lSock; |
|
331 try{ |
|
332 lSock = new DatagramSocket(iUdpPort); |
|
333 } |
|
334 catch(SocketException e){ |
|
335 System.out.println(e); |
|
336 return; |
|
337 } |
|
338 int lTempResult = -1; |
|
339 // echo back everything to new socket |
|
340 while (true){ |
|
341 |
|
342 try{ |
|
343 DatagramPacket lPack = new DatagramPacket(new byte[iBufferSize], iBufferSize); |
|
344 |
|
345 lSock.receive(lPack); |
|
346 |
|
347 // Set IP address of remote socket |
|
348 InetAddress lIpAddress = lPack.getAddress(); |
|
349 iClientHost = lIpAddress.getHostAddress(); |
|
350 System.out.println("Received from IP Address: " + iClientHost); |
|
351 |
|
352 int lLengthOfData = lPack.getLength(); |
|
353 |
|
354 if (lLengthOfData <= 0){ |
|
355 continue; |
|
356 } |
|
357 |
|
358 byte[] lData = lPack.getData(); |
|
359 String lMessage = new String(lData, 0, lLengthOfData); |
|
360 System.out.println("Server: " + lMessage); |
|
361 |
|
362 lTempResult = parseIntCommand(lMessage, iCommandReceiveBufferSize); |
|
363 if (lTempResult != -1){ // Message parsed |
|
364 if (lTempResult > 0){ |
|
365 iReceiveBufferLength = lTempResult; |
|
366 lSock.setReceiveBufferSize(iReceiveBufferLength); |
|
367 System.out.println("RECEIVE BUFFER LENGTH SET TO " + lSock.getReceiveBufferSize()); |
|
368 } |
|
369 else{ |
|
370 System.out.println("INVALID RECEIVE BUFFER LENGTH: " + iReceiveBufferLength); |
|
371 } |
|
372 } |
|
373 |
|
374 lTempResult = parseIntCommand(lMessage, iCommandSendBufferSize); |
|
375 if (lTempResult != -1){ // Message parsed |
|
376 if (lTempResult > 0){ |
|
377 iSendBufferLength = lTempResult; |
|
378 } |
|
379 else{ |
|
380 System.out.println("INVALID SEND BUFFER LENGTH: " + lTempResult); |
|
381 } |
|
382 } |
|
383 |
|
384 parsePort(lMessage); |
|
385 |
|
386 if (lMessage.startsWith(iCommandStartReturning)){ |
|
387 System.out.println("ECHOING ACTIVATED"); |
|
388 iEchoData = true; |
|
389 } |
|
390 |
|
391 if (lMessage.startsWith(iCommandShutdownNow)){ |
|
392 System.out.println("SHUTTING DOWN"); |
|
393 lSock.close(); |
|
394 return; |
|
395 } |
|
396 |
|
397 if (iPortSet && iEchoData){ |
|
398 sendUDP(lMessage); |
|
399 } |
|
400 |
|
401 if (lMessage.startsWith(iCommandShutdown)){ |
|
402 System.out.println("SHUTTING DOWN"); |
|
403 lSock.close(); |
|
404 return; |
|
405 } |
|
406 |
|
407 if (lMessage.startsWith(iCommandStopReturning)){ |
|
408 System.out.println("ECHOING DEACTIVATED"); |
|
409 iEchoData = false; |
|
410 } |
|
411 |
|
412 int lSleepLength = parseIntCommand(lMessage, iCommandSleep); |
|
413 if (lSleepLength != -1){ // Message parsed |
|
414 if (lSleepLength > 0){ |
|
415 System.out.println("SLEEPING FOR " + lSleepLength + " MILLISECONDS"); |
|
416 try{ |
|
417 java.lang.Thread.sleep(lSleepLength); |
|
418 } |
|
419 catch(java.lang.InterruptedException ie){ |
|
420 System.err.println("Sleep inturrupted."); |
|
421 } |
|
422 } |
|
423 else{ |
|
424 System.out.println("INVALID SLEEP LENGTH: " + lSleepLength + " MILLISECONDS"); |
|
425 } |
|
426 } |
|
427 } |
|
428 catch(IOException ioe){ |
|
429 System.out.println(ioe); |
|
430 try{ |
|
431 lSock.close(); |
|
432 } |
|
433 catch(Exception e){ |
|
434 System.err.println(e); |
|
435 } |
|
436 return; |
|
437 } |
|
438 } |
|
439 } |
|
440 |
|
441 private void sendUDP(String aMessage){ |
|
442 |
|
443 try{ |
|
444 byte[] lMessage = aMessage.getBytes(); |
|
445 System.out.println("Echo to host: " + iClientHost + ":" + iClientPort); |
|
446 |
|
447 InetAddress lAddress = InetAddress.getByName(iClientHost); |
|
448 // Initialize a datagram packet with data and address |
|
449 DatagramPacket lPacket = new DatagramPacket(lMessage, lMessage.length, lAddress, iClientPort); |
|
450 |
|
451 // Create a datagram socket, send the packet through it, close it. |
|
452 DatagramSocket lDSocket = new DatagramSocket(); |
|
453 |
|
454 if (iSendBufferLength > 0){ |
|
455 lDSocket.setSendBufferSize(iSendBufferLength); |
|
456 System.out.println("SEND BUFFER LENGTH SET TO " + lDSocket.getSendBufferSize()); |
|
457 } |
|
458 |
|
459 lDSocket.send(lPacket); |
|
460 lDSocket.close(); |
|
461 } |
|
462 catch(Exception e){ |
|
463 System.err.println(e); |
|
464 } |
|
465 } |
|
466 } |