Java: Multithreading & UDP Socket Programming

后端 未结 4 870
闹比i
闹比i 2021-02-10 18:42

I am new to multithreading & socket programming in Java. I would like to know what is the best way to implement 2 threads - one for receiving a socket and one for sending a

4条回答
  •  一向
    一向 (楼主)
    2021-02-10 18:47

    It's a good thing Eclipse's history works even for a day back :) Thanks to that, I am able to give both Ravi a working example and Lirik his answer on leakage.

    Let me first start of by stating that I have no clue what is causing this leak, but if I leave it long enough, it will fail on a OutOfMemoryError.

    Second, I left the working code commented out for Ravi for a working basic example of my UDP server. The timeout was there to test how long my firewall would kill the receivers end (30 seconds). Just remove anything with the pool, and you're good to go.

    So here is, a working but leaking version of my example threaded UDP server.

    public class TestServer {
    
    private static Integer TIMEOUT = 30;
    private final static int MAX_BUFFER_SIZE = 8192;
    private final static int MAX_LISTENER_THREADS = 5;
    private final static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss.SSSZ");
    
    private int mPort;
    private DatagramSocket mSocket;
    
    // You can remove this for a working version
    private ExecutorService mPool;
    
    public TestServer(int port) {
        mPort = port;
        try {
            mSocket = new DatagramSocket(mPort);
            mSocket.setReceiveBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSendBufferSize(MAX_BUFFER_SIZE);
            mSocket.setSoTimeout(0);
    
            // You can uncomment this for a working version
            //for (int i = 0; i < MAX_LISTENER_THREADS; i++) {
            //  new Thread(new Listener(mSocket)).start();
            //}
    
            // You can remove this for a working version
            mPool = Executors.newFixedThreadPool(MAX_LISTENER_THREADS);
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // You can remove this for a working version
    public void start() {
        try {
            try {
                while (true) {
                    mPool.execute(new Listener(mSocket));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } finally {
            mPool.shutdown();
        }
    }
    
    private class Listener implements Runnable {
    
        private final DatagramSocket socket;
    
        public Listener(DatagramSocket serverSocket) {
            socket = serverSocket;
        }
    
        private String readLn(DatagramPacket packet) throws IOException {
            socket.receive(packet);
            return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(packet.getData())), MAX_BUFFER_SIZE).readLine();
        }
    
        private void writeLn(DatagramPacket packet, String string) throws IOException {
            packet.setData(string.concat("\r\n").getBytes());
            socket.send(packet);
        }
    
        @Override
        public void run() {
            DatagramPacket packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
            String s;
            while (true) {
                try {
                    packet = new DatagramPacket(new byte[MAX_BUFFER_SIZE], MAX_BUFFER_SIZE);
                    s = readLn(packet);
                    System.out.println(DateFormat.format(new Date()) + " Received: " + s);
                    Thread.sleep(TIMEOUT * 1000);
                    writeLn(packet, s);
                    System.out.println(DateFormat.format(new Date()) + " Sent: " + s);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    public static void main(String[] args) {
        if (args.length == 1) {
            try {
                TIMEOUT = Integer.parseInt(args[0]);
            } catch (Exception e) {
                TIMEOUT = 30;
            }
        }
        System.out.println(DateFormat.format(new Date()) + " Timeout: " + TIMEOUT);
        //new TestServer(4444);
        new TestServer(4444).start();
    }
    }
    

    btw. @Lirik, I witnessed this behavior first in Eclipse, after which I tested it from the command line. And again, I have NO clue what is causing it ;) sorry...

提交回复
热议问题