Прислушивание к TCP и UDP запрашивает на том же порте

Я пишу Клиент-серверный набор программ

В зависимости от операции, которую требует клиент, я использую, делают запрос UDP или TCP.

Реализация стороны клиента проста, так как я могу легко открыть соединение с любым протоколом и отправить запрос к серверной стороне.

На стороне серверов, с другой стороны, я хотел бы послушать и для соединений UDP и для соединений TCP на том же порте. Кроме того, мне нравится, когда сервер открывает новый поток для каждого запроса на установление соединения.

Я принял подход, объясненный в: текст ссылки

Я расширил этот пример кода путем создания новых потоков для каждого запроса TCP/UDP.

Это работает правильно, если я использую TCP только, но он перестал работать, когда я пытаюсь сделать привязку UDP.

Дайте мне какое-либо предложение, как я могу исправить это.

tnx

Вот Серверный код:

public class Server {
public static void main(String args[]) {
    try {
        int port = 4444;
        if (args.length > 0)
            port = Integer.parseInt(args[0]);

        SocketAddress localport = new InetSocketAddress(port);

        // Create and bind a tcp channel to listen for connections on.
        ServerSocketChannel tcpserver = ServerSocketChannel.open();
        tcpserver.socket().bind(localport);

        // Also create and bind a DatagramChannel to listen on.
        DatagramChannel udpserver = DatagramChannel.open();
        udpserver.socket().bind(localport);

        // Specify non-blocking mode for both channels, since our
        // Selector object will be doing the blocking for us.
        tcpserver.configureBlocking(false);
        udpserver.configureBlocking(false);

        // The Selector object is what allows us to block while waiting
        // for activity on either of the two channels.
        Selector selector = Selector.open();

        tcpserver.register(selector, SelectionKey.OP_ACCEPT);
        udpserver.register(selector, SelectionKey.OP_READ);

        System.out.println("Server Sterted on port: " + port + "!");

        //Load Map
        Utils.LoadMap("mapa");
        System.out.println("Server map ... LOADED!");

        // Now loop forever, processing client connections
        while(true) {
            try { 
                selector.select();
                Set keys = selector.selectedKeys();

                // Iterate through the Set of keys.
                for (Iterator i = keys.iterator(); i.hasNext();) {
                    SelectionKey key = i.next();
                    i.remove();

                    Channel c = key.channel();

                    if (key.isAcceptable() && c == tcpserver) {
                        new TCPThread(tcpserver.accept().socket()).start();
                    } else if (key.isReadable() && c == udpserver) {
                        new UDPThread(udpserver.socket()).start();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.err.println(e);
        System.exit(1);
    }
}

}

Код UDPThread:

public class UDPThread extends Thread {
private DatagramSocket socket = null;

public UDPThread(DatagramSocket socket) {
    super("UDPThread");
    this.socket = socket;
}

@Override
public void run() {
    byte[] buffer = new byte[2048];
    try {           
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        socket.receive(packet);

        String inputLine = new String(buffer);
        String outputLine = Utils.processCommand(inputLine.trim());

        DatagramPacket reply = new DatagramPacket(outputLine.getBytes(), outputLine.getBytes().length,
                                                  packet.getAddress(), packet.getPort());
        socket.send(reply);

    } catch (IOException e) {
        e.printStackTrace();
    }
    socket.close(); 
}

}

Я получаю:

Exception in thread "UDPThread" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.DatagramSocketAdaptor.receive(Unknown Source)
at server.UDPThread.run(UDPThread.java:25)

10x

6
задан Jonik 12 May 2010 в 14:44
поделиться

3 ответа

AFAIK, вы должны иметь возможность прослушивать как TCP-соединения, так и UDP-сообщения на одном и том же порте. Было бы полезно, если бы вы разместили свой UDP-код и исключение + stacktrace, которое вы видите.

0
ответ дан 17 December 2019 в 20:29
поделиться

Это должно работать. Одна из проблем с этим кодом, похоже, заключается в том, что размер ByteBuffer установлен в 0, что означает, что датаграмма отбрасывается (о чем говорится в комментариях). Если вам нужно получать какую-либо информацию по UDP и вы находитесь в надежной сети, вы можете установить довольно большой размер и получать большие дейтаграммы, состоящие из нескольких пакетов. В противном случае, в ненадежной сети, установите этот размер равным MTU. Убедитесь, что вы перевернули() ByteBuffer после того, как получили в него что-либо.

Кроме того, создание новых потоков для каждого запроса - плохая идея, создайте поток 'session' для каждого IP, который вы получаете в HashMap или что-то вроде того, а затем выполните guarded block на объекте session. Пробудите поток, спящий на этом объекте, когда получите сообщение после передачи новой информации. Имеющийся у вас код селектора предназначен для избежания создания потоков таким образом.

Edit: исходя из приведенного выше кода, вы создаете дейтаграммный канал, а затем используете сокет для получения дейтаграмм напрямую? Это не имеет смысла. Используйте методы канала только после привязки канала. Также не делайте это в отдельном потоке. Ваш код не является потокобезопасным и сам себя сломает. Передавайте полученную информацию в отдельный поток 'session', как упоминалось ранее. Селектор предназначен для того, чтобы сказать вам, с каких каналов можно читать без блокировки (хотя блокировка отключена в любом случае, поэтому он скажет вам, с каких каналов есть данные для чтения).

3
ответ дан 17 December 2019 в 20:29
поделиться

Вы не можете использовать DatagramSocket.receive () в неблокирующем режиме. Вы должны использовать методы read () или receive () вашего DatagramChannel напрямую.

Фактически, поскольку вы используете неблокирующий режим и селектор , совершенно невозможно понять, почему вы вообще используете UDPThread . Просто вызовите udpserver.receive () вместо запуска потока.

-1
ответ дан 17 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: