UDP DatagramPacket не получен от внешнего клиента

У меня есть игра с сервером UDP/TCP и клиентом. Один порт UDP (2406) для обновления местоположения клиента и один порт TCP (2407) для чата. Проблема здесь на 2406.

Когда я играю в клиенты в своей локальной сети, все работает нормально. Но когда внешний клиент хочет присоединиться, я получаю только первый пакет (команду присоединения) и после этого... ничего. Я (зашел в локальную сеть) не вижу внешний плеер. НО они меня видят. Чат работает для обеих сторон. Так что это действительно связано с DatagramSocket. Я постараюсь опубликовать как можно больше информации, касающейся UDP, а не TCP.

Кто-нибудь знает, в чем здесь проблема?

Порты перенаправляются, например UDP 2406, TCP 2407.

Сервер, сокеты:

DatagramSocket socket = new DatagramSocket(2406, InetAddress.getLocalHost());
ServerSocket serversocket_chat = new ServerSocket(2407, 0, InetAddress.getLocalHost());

Сервер, поток приема:

byte[] buffer = new byte[1024];
DatagramPacket dp = new DatagramPacket(buffer, 1024);

while(true){
    try{
        this.socket.receive(dp);

        String data = new String(dp.getData(), 0, dp.getLength()).trim();
        String[] args = data.split(":");
        String command = args[0];

        String reply = null;
        try{
            reply = handleCommand(dp, command, args);
        } catch( Exception e ){
            System.err.println("Error while handling command: " + command);
            e.printStackTrace();
        }

        if(reply != null){
            reply += "\n";
            DatagramPacket reply_packet = new DatagramPacket(reply.getBytes(), reply.length(), dp.getSocketAddress());

            this.socket.send(reply_packet);
        }

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

new Thread(chat_receive).start();

Как только кто-то отправит сообщение, метод handleCommand узнает, что это такое. Каждое сообщение представляет собой байт [], полученный из строки. Если сообщение "cj:Hello", handleCommand находит команду cs, имя пользователя Hello. ЭТО получено сервером. После этого, если тот же человек что-то отправит, ничего не будет получено.

Клиентские сокеты:

private DatagramSocket socket;
private Socket socket_chat;

Подключение клиента:

this.socket = new DatagramSocket();
this.socket_chat = new Socket(ip, port+1);

Отправка клиента:

private Runnable send = new Runnable() {
    @Override
    public void run() {
        DatagramPacket dp;
        String sendStringBuffered;
        while(true){
            if(sendString != null){
                sendStringBuffered = sendString;
                dp = new DatagramPacket(sendStringBuffered.getBytes(), sendStringBuffered.length(), ip, port);
                try {
                    socket.send(dp);
                } catch (IOException ex) {
                    Logger.getLogger(NewClient.class.getName()).log(Level.SEVERE, null, ex);
                }
                 sendString = null;
            }
        }
    }
};

person Stefan Schouten    schedule 02.10.2012    source источник


Ответы (1)


На ум приходят две вещи:

  • UDP не надежен. Дейтаграмма может быть потеряна в любой момент
  • Пакеты UDP обычно не проходят через NAT просто так.

Для систематического устранения неполадок убедитесь, что пакеты действительно доходят до адресата, используя анализатор/анализатор пакетов (например, tcpdump или wireshark).

person wnrph    schedule 02.10.2012
comment
Ох, хорошо. Самое смешное, что вообще никакие пакеты, кроме первого, не проходят от внешнего клиента к моему серверу. Как вы думаете, я все равно должен использовать TCP? Я не знаком со снифферами/анализаторами пакетов, поэтому их использование будет целым процессом обучения. Но если вы предложите это, я постараюсь выяснить. - person Stefan Schouten; 02.10.2012
comment
Wireshark довольно прост (особенно для этой цели). Вы должны быть в порядке с этим. - person wnrph; 02.10.2012
comment
Хорошо, я попробую, спасибо. Я надеюсь, что смогу выяснить, почему мой сервер может отправлять, но не получать от внешнего клиента. - person Stefan Schouten; 02.10.2012