Датаграмма UDP отправлена, но никогда не получена

#java #udp #datagram

Вопрос:

Я создал два разных класса java, для клиента и для сервера, с методами отправки и получения в каждом. В соответствии с задачей я должен был установить соединение сервер-клиент через DatagramPacket и соединение клиент-сервер через DatagramChannel . Последний отлично работает, но у меня проблемы с датаграммами-они отправляются с сервера и никогда не поступают на клиент. Что случилось?

 public class TransferClient implements Serializable{
    private static final long serialVersionUID = 26L;
    public TransferClient() {

    }

    public void send(Command com) throws IOException {
        SocketAddress socketAddressChannel = new InetSocketAddress("localhost", 1);
        DatagramChannel datagramChannel=DatagramChannel.open();
        ByteBuffer bb;
        datagramChannel.connect(socketAddressChannel);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(com);
        oos.flush();
        bb=ByteBuffer.wrap(baos.toByteArray(),0, baos.size());
        datagramChannel.send(bb,socketAddressChannel);
        baos.close();
        oos.close();
    }

    public Command receive() throws IOException, ClassNotFoundException {
        SocketAddress address = new InetSocketAddress(2029);
        DatagramSocket s = new DatagramSocket();
        DatagramPacket inputPacket = new DatagramPacket(new byte[1024],1024, address);
        s.receive(inputPacket);
        ByteArrayInputStream bais = new ByteArrayInputStream(inputPacket.getData());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (Command) ois.readObject();
    }
}

public class TransferServer {
    public TransferServer(){

    }

    public void send(Command com) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        byte[] buffer;
        oos.writeObject(com);
        oos.flush();
        buffer=baos.toByteArray();
        SocketAddress address = new InetSocketAddress("localhost",2029);
        DatagramSocket s = new DatagramSocket();
        DatagramPacket outputPacket = new DatagramPacket(buffer,buffer.length,address);
        s.send(outputPacket);
    }


    public Command receive() throws IOException, ClassNotFoundException {
            SocketAddress socketAddressChannel = new InetSocketAddress("localhost", 1);
            DatagramChannel datagramChannel = DatagramChannel.open();
            datagramChannel.bind(socketAddressChannel);
            ByteBuffer bb = ByteBuffer.allocate(1024);
            datagramChannel.receive(bb);
            ByteArrayInputStream bais = new ByteArrayInputStream(bb.array());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Command command;
            System.out.println(ois.available());
            command =(Command) ois.readObject();
            datagramChannel.close();
            ois.close();
            bais.close();
            return command;
    }
}
 

Комментарии:

1. Порты ниже 1024 защищены. Похоже, вы используете очень низкие цифры.

2. О боже, я поменял порты, но это не помогло. Тем не менее, спасибо!

Ответ №1:

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

И вам не нужно SocketAddress здесь, но вам нужно учитывать фактическую длину полученного пакета.

См.Документацию java.net. DatagramSocket

В receive() методе вашего TransferClient класса:

 public Command receive() throws IOException, ClassNotFoundException {

    DatagramSocket s = new DatagramSocket(2029); //Add your port Here

    DatagramPacket inputPacket = new DatagramPacket(new byte[1024],1024);
    s.receive(inputPacket);
    ByteArrayInputStream bais = new ByteArrayInputStream(inputPacket.getData(), 0, packet.getLength());
    ObjectInputStream ois = new ObjectInputStream(bais);
    return (Command) ois.readObject();
}
 

Комментарии:

1. Но затем он выдает исключение BindException: Адрес уже используется: привязка. Чтобы прояснить ситуацию: сначала я отправляю данные с клиента на сервер, а затем-с сервера на клиента.

2. Обязательно не устанавливайте порт DatagramSocket в send() методе вашего сервера, это может быть причиной исключения.

3. Я не устанавливаю его в методе отправки() сервера.

4. На самом деле я установил его в посылке. Может ли это исключение быть вызвано этим?

5. Это происходит потому, что вы открываете сокет каждый раз, когда вводите этот метод, и никогда не закрываете его. Вы должны создать сокет перед вводом метода один раз и закрыть его, когда вы полностью закончите с ним.