Многоадресные пакеты приходят грязными

Я делаю очень простое многоадресное приложение, в котором контроллер блокирует и разблокирует станцию ​​с помощью простых сообщений. Контроллер и станция имеют потоки получателя. По какой-то причине, когда отправляется первое сообщение, оно принимается хорошо, а когда отправляется второе сообщение, оно принимается неправильно, с прикрепленным к нему частью первого сообщения.

Например,

Station 1 sends a "Locked: 1001" message.
The controller receives this message correctly.
The controller sends a "Unlock: 1001" message.
Station 1 receives something like "Unlock: 1ocked: 1001"

Вот приемник станции:

public class VotingStationReceiver implements Runnable{
    private DummyVotingStation votingStation;
    private MulticastSocket s;
    private Thread listener = new Thread(this);

    public VotingStationReceiver(MulticastSocket s, DummyVotingStation votingStation){
        this.s = s;
        this.votingStation = votingStation;

        listener.start();
    }

    public void run() {
        byte[] buf = new byte[1024]; 
        while(true) 
            try { 
                DatagramPacket pack = new DatagramPacket(buf, buf.length);
                s.receive(pack);
                String msg = "";
                msg = new String(pack.getData());
                msg = msg.trim();

                System.out.println(msg);
                System.out.println("Voting Station: message received");

                votingStation.processMessage(msg);

            } catch(IOException e) { 
                    break; 
            } 
    }

}

А вот куда отправляется сообщение контроллера:

    private String unlockMsg = "Unlock: ";
    public void unlockStation(int lockedID) {
        //send packet telling station to unlock
        String completeMsg = unlockMsg+lockedID;
        byte buf[] = completeMsg.getBytes(); 
        // Create and send the DatagramPacket
        DatagramPacket pack;
        try {
            pack = new DatagramPacket(buf, buf.length,
                    InetAddress.getByName(group), port);
            int ttl = s.getTimeToLive();
            s.setTimeToLive(ttl);
            s.send(pack);
            System.out.println("Control Station: message sent");
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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


person Tuma    schedule 14.04.2014    source источник


Ответы (2)


Я подозреваю, что ваша проблема заключается в том, что вы получаете Datagram в существующий буфер, в котором есть данные из предыдущего квитанции Datagram. Попробуйте использовать новый byte[] для каждого приема. Я также думаю, что вам нужно учитывать длину поступающих данных и, следовательно, проверять этот ТАК ответ, чтобы использовать pack.getLength()

person Brian Agnew    schedule 14.04.2014
comment
Ничего себе, абсолютно ошибка новичка. Спасибо, это была проблема. - person Tuma; 14.04.2014
comment
Половина права. Это решение работает, но есть лучший способ сделать это. - person Stephen C; 14.04.2014

Проблема в том, что вы не обращаете внимания на длину пакета, который вы получили. Изменять

    msg = new String(pack.getData());

to

    msg = new String(pack.getData(), 0, pack.getLength());

В первый раз, когда вы создаете строку в своем коде, она (вроде) работает .... потому что вы затем trim() строку, чтобы избавиться от завершающих символов NUL (нуля).

Во второй раз вы читаете в грязный буфер, поэтому мусор декодируется как символы, отличные от NUL.

FWIW, если вы используете длину пакета при создании строки, больше нет необходимости trim(), чтобы избавиться от завершающих символов NUL.

person Stephen C    schedule 14.04.2014