Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have multiple threads listening on the same DatagramSocket?

I'm writing a chat program in java and I have been stuck for hours with this problem. This is my class that waits for clients to connect to the server. Every time a new client connects I create a new ChatClient(String name, DatagramSocket serverSocket,InetAddress IPAddress, int port) object.

My idea was that every ChatClient object listens on the socket and when a package is sent from the same IP as the ChatClient, it will handle it, otherwise do nothing.

As it is now, when I only have one client connected; the client gets every 2 packages, then run() in WaitForConnection() gets the rest.

So my question, is it possible to have multiple threads listening on the same DatagramSocket without loss (everyone gets everything send). If there is a solution, how?

private ArrayList<ChatClient> clients;
    private DatagramSocket serverSocket;
    private boolean running;

    public WaitForConnection() {
        running = true;
        clients = new ArrayList<ChatClient>();

        try {
            serverSocket = new DatagramSocket(ChatServer.port);
        } catch (SocketException e) {
            System.out
                    .println("Couldn't open socket. Port might alreadybe in use");
            e.printStackTrace();
        }
        try {
            serverSocket.setReuseAddress(true);
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void run() {

        while (running) {
            for (ChatClient ch : clients) {
                System.out.println(ch.toString());
            }

            byte[] handShake = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(handShake,
                    handShake.length);

            try {
                serverSocket.receive(receivePacket);
            } catch (IOException e) {
                System.out.println("Waiting for connections error");
                e.printStackTrace();
            }
            String connect = new String(receivePacket.getData());
            System.out.println(connect);

            InetAddress IPAddress = receivePacket.getAddress();

            // if connect == "OPEN_CONNECTION" -> new client want to connect.
            if (connect.contains("openconnection")) {

                int port = receivePacket.getPort();

                try {

                    ChatClient chatClient = new ChatClient(
                            IPAddress.getHostName(), serverSocket, IPAddress,
                            port);

                    // Don't want double clients.
                    for (int i = 0; i < clients.size(); i++) {
                        if (clients.get(i).equals(chatClient)) {
                            clients.remove(i);
                        }
                    }
                    clients.add(chatClient);

                } catch (IOException e) {
                    System.out.println("Couldn't connect to client");
                    e.printStackTrace();
                }
            }
        }
    }
}

Code for ChatClient if you need to look at it.

public class ChatClient extends Thread {
    private InetAddress IPAddress;
    private DatagramSocket serverSocket;
    private int port;
    private String name;

    public ChatClient(String name, DatagramSocket serverSocket,
            InetAddress IPAddress, int port) throws IOException {
        super(name);
        this.name = name;
        this.IPAddress = IPAddress;
        this.serverSocket = serverSocket;
        this.port = port;

        byte[] confirmConnection = new byte[1024];
        String connected = "Connection to server established";
        confirmConnection = connected.getBytes();

        serverSocket.send(new DatagramPacket(confirmConnection,
                confirmConnection.length, IPAddress, port));
        start();

    }

    public void run() {
        while (true) {
            byte[] message = new byte[1024];
            DatagramPacket receivedPacket = new DatagramPacket(message,
                    message.length);
            try {
                serverSocket.receive(receivedPacket);
            } catch (IOException e) {
                System.out
                        .println("Something went wrong receiving data in ChatClient");
            }
            if (receivedPacket.getAddress().equals(IPAddress)) {
                String connect = new String(receivedPacket.getData());
                connect = connect.toUpperCase();
                System.out.println(connect + "client side");
                message = connect.getBytes();
                try {
                    serverSocket.send(new DatagramPacket(message,
                            message.length, IPAddress, port));
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}
like image 894
Jakkra Avatar asked Oct 28 '25 07:10

Jakkra


2 Answers

It is possible for multiple threads to receive from the same DatagramSocket, but only one of them will get each datagram.

I don't see why you think you need this.

like image 193
user207421 Avatar answered Oct 29 '25 20:10

user207421


It is technically not possible, because the network hardware receives the packet only once. But then you can always duplicate it in memory once it is read. In your code basically just do Arrays.copyOf(receivePacket)

For a more sophisticated version, you could use the NIO package and work with a Selector. This would allow you to have all network connections run through a single thread, that reads and distributes the data to processing threads. That saves you the extra threading-overhead if you have multiple connections from many clients.

like image 41
TwoThe Avatar answered Oct 29 '25 21:10

TwoThe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!