I write kind of UDP server. It should serves about 50 messages per second. I would like a review about the general code 'quality' and logic. The server uses the same socket for sending and receiving messages. The messages are short - about 100 bytes (json).
The code:
public class UdpServer extends Thread {
/* Receive timeout in mills */
private static int RCV_TIMEOUT = 100;
/* Buffer size */
final private static int BUFF_SIZE = 512;
/* Number of concurrent handlers */
final private static int THREAD_POOL_SIZE = 10;
/* Socket */
final private DatagramSocket socket;
/* Thread pool executor */
final private ThreadPoolExecutor executor;
/* Termination states */
private boolean terminated = false; //set to true if this server is terminated
private boolean terminating = false; //set to true if this server is in the process of terminating
/*
* Debug flag. If it is ON then server sends
* debug messages to clients
*/
private final static boolean debugModeOn = false;
/*
* Transmitter to use by handler to send response to request
* originator. It encapsulates socket, so handler may only send data.
*/
private DatagramResponder responder;
public UdpServer (String ip, int port)
throws ValidationException, SocketException {
if (port <= 0)
throw new ValidationException("Illegal port: " + port);
InetAddressValidator validator = InetAddressValidator.getInstance();
if (!validator.isValidInet4Address(ip) && !validator.isValidInet6Address(ip))
throw new ValidationException("Illegal Ip address: " + ip);
if (!Utils.isIpLocalAndUp(ip))
throw new ValidationException("Given IP is not a local IP or interface is down");
SocketAddress socketAddress = new InetSocketAddress(ip, port);
socket = new DatagramSocket(socketAddress);
socket.setSoTimeout(RCV_TIMEOUT);
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(THREAD_POOL_SIZE);
responder = new Responder (socket);
}
public void run() {
while (!terminated) {
byte[] buf = new byte[BUFF_SIZE];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
socket.receive(packet);
} catch (SocketTimeoutException to) {
if (!terminated) continue;
else break;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (!terminating) {
Runnable handler = HandlerFactory.getHandler(packet, responder);
executor.execute(handler);
}
}
socket.close();
}
/**
* @return true if server debug mode is ON
*/
public static boolean isDebugModeOn() {
return debugModeOn;
}
/*
* Stops the server. The method waits (up to 60 seconds)
* until all tasks have completed execution
*/
public void terminate () throws IOException {
if (terminating || terminated)
return;
terminating = true;
try {
executor.awaitTermination(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {};
executor.shutdownNow();
terminated = true;
}
//for resting only, will be removed
private static void setReceiveTO (int timeOut) {
RCV_TIMEOUT = timeOut;
}
private static class Responder implements DatagramResponder {
private DatagramSocket socket;
private Responder (DatagramSocket socket) {
this.socket = socket;
}
@Override
public void send(DatagramPacket packet) throws IOException, SecurityException,
PortUnreachableException, IllegalBlockingModeException, IllegalArgumentException {
socket.send(packet);
}
}
public static void main(String[] args) throws ValidationException, IOException, InterruptedException {
//Test that we can send data while socket is blocked on receive
UdpServer.setReceiveTO(1000 * 60 * 60); //1 hour
UdpServer server = new UdpServer ("127.0.0.1", 1234);
server.start();
TestReceiver rcv = new TestReceiver();
rcv.start();
TestSender tester = new TestSender(server.socket);
tester.start();
}
//Receiver
private static class TestReceiver extends Thread {
private DatagramSocket socket;
private TestReceiver () throws SocketException {
socket = new DatagramSocket(1000);
}
public void run() {
while (true) {
try {
byte [] buf = new byte[100];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
System.out.println("Received: " + new String (packet.getData()));
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
}
}
private static class TestSender extends Thread {
private DatagramSocket socket;
private byte [] buf = "hello".getBytes();
private int port = 1000;
private InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
private DatagramPacket packet = new DatagramPacket(buf, buf.length, address.getAddress(), port);
private TestSender (DatagramSocket socket) {
this.socket = socket;
}
public void run() {
while (true) {
try {
socket.send(packet);
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
}
}
}
...
. Is it complete? \$\endgroup\$