UDP-трансляция в Java

Утро.

Я довольно новичок в соединениях Java и сокетов, но я пытаюсь отправить UDP-пакет/трансляцию на 255.255.255.255 через порт 8001 на устройство. Я могу получить данные для отправки просто отлично, однако, когда приходит время получать данные, время ожидания соединения истекает. У меня есть анализатор пакетов, и я вижу, как пакет отправляется, а затем устройство отвечает.

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

 m_Socket = new DatagramSocket(m_SERVERPORT);
 InetAddress address = InetAddress.getByName(m_SERVERIP);


 m_DataPack = new DatagramPacket(m_SERVERCMD.getBytes(), m_SERVERCMD.getBytes().length,
 address, m_SERVERPORT);
 m_Socket.setBroadcast(true);
 m_Socket.connect(address, m_SERVERPORT);

 m_Socket.send(m_DataPack);
 m_DataPack = new DatagramPacket(data, data.length,
 address, m_SERVERPORT);


 m_Socket.receive(m_DataPack); // This is where it times out


 data = m_DataPack.getData();
 String received = data.toString();
 System.out.println("Received: " + received);
 m_Socket.close();

Спасибо и Gig'Em.

РЕДАКТИРОВАТЬ:

Я не уверен, поможет ли это, но когда я смотрю объект m_Socket, я вижу следующее прямо перед его отправкой:

bound = true;
close = false;
connectedAddress = Inet4Address (id = 32) (-1,-1,-1,-1);
connectedPort = 8001;
connectState = 1;
created = true;
impl = PlainDatagramSocketImpl;
oldImpl = false;

а объект m_DataPack следующий:

address = Inet4Address (id = 32) (-1,-1,-1,-1);
bufLength = 6 (size of packet I'm sending is 6 char long);
offset = 0;
port = 8001;

person user355528    schedule 01.06.2010    source источник
comment
Вы понимаете, что ваш Gig'Em отталкивает некоторых выпускников одной из самых крупных программ CS в Америке, верно?   -  person jasonmp85    schedule 02.06.2010
comment
@jasonmp85 для тех, кто не является техасцем, кому интересно, что это значит: en.wikipedia. org/wiki/ (да, надо было поискать ;))   -  person Matthieu    schedule 03.10.2017


Ответы (4)


Это не имеет смысла. Вы ведете широковещательную передачу, то есть 1 ко многим, и вы также подключаетесь, то есть 1 к 1. Что он?

Потерять связь. И потерять 255.255.255.255. Это сильно устарело около 20 лет. Используйте локальный широковещательный адрес подсети, например. 192.168.1.255.

person user207421    schedule 02.06.2010

Вы также можете взглянуть на MulticastSocket, описанный в разделе Рассылка нескольким получателям. Надеюсь это поможет.

person Zorayr    schedule 16.02.2012

Если вы хотите получить дейтаграмму, вам необходимо bind() с локальной конечной точкой (адрес + порт).

person John Kugelman    schedule 01.06.2010
comment
В функции привязки мне нужно установить локальную конечную точку на адрес и порт через SocketAddress. Как лучше всего это сделать? Я знаю, что в классе DatagramPacket есть getSocketAddress(); функция, так что это не помогает мне. - person user355528; 01.06.2010
comment
Я пробовал m_DataPack = new DatagramPacket(data, data.length, InetAddress.getLocalHost(), m_SERVERPORT); а затем m_Socket.bind(m_DataPack.getSocketAddress()); но он выдает исключение, говорящее, что сокет уже привязан. - person user355528; 01.06.2010
comment
Он связывает, вот что делает new DatagramSocket(int port). - person user207421; 02.06.2010

Вы отправляете и получаете пакет на одном устройстве. Вы можете разделить порты отправки и получения (например, отправить на 8001, получить на 8002). И запускайте коды отправки и получения как отдельные потоки. Если оба устройства должны найти друг друга (или одно устройство должно найти себя).

import java.io.IOException;
import java.net.*;

Получение:

private DatagramSocket getReceiveSocket() throws UnknownHostException, SocketException {
    if (receiveSocket == null) {
        receiveSocket = new DatagramSocket(8002, InetAddress.getByName("0.0.0.0")); // 0.0.0.0 for listen to all ips
        receiveSocket.setBroadcast(true);
    }
    return receiveSocket;
}

public void receive() throws IOException {
    // Discovery request command
    byte[] buffer = "__DISCOVERY_REQUEST__".getBytes();
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
    getReceiveSocket().receive(packet);
    System.out.println("Discovery package received! -> " + packet.getAddress() + ":" + packet.getPort());
    // Get received data
    String data = new String(packet.getData()).trim();
    if (data.equals("__DISCOVERY_REQUEST__")) { // validate command
        // Send response
        byte[] response = new byte["__DISCOVERY_RESPONSE".length()];
        DatagramPacket responsePacket = new DatagramPacket(response, response.length, packet.getAddress(), packet.getPort());
        getReceiveSocket().send(responsePacket);
        System.out.println("Response sent to: " + packet.getAddress() + ":" + packet.getPort());
    } else {
        System.err.println("Error, not valid package!" + packet.getAddress() + ":" + packet.getPort());
    }
}

Отправка:

private DatagramSocket getSendSocket() throws UnknownHostException, SocketException {
    if (sendSocket == null) {
        sendSocket = new DatagramSocket(8001, InetAddress.getLocalHost());
        sendSocket.setBroadcast(true);
    }
    return sendSocket;
}

public void send() throws IOException {
    // Discovery request command
    byte[] data = "__DISCOVERY_REQUEST__".getBytes();
    DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("255.255.255.255"), 8002);
    getSendSocket().send(packet);
    System.out.println("Discovery package sent!" + packet.getAddress() + ":" + packet.getPort());

    // Discovery response command
    byte[] response = new byte["__DISCOVERY_RESPONSE__".length()];
    DatagramPacket responsePacket = new DatagramPacket(response, response.length);
    getSendSocket().receive(responsePacket);
    System.out.println("Discovery response received!" + responsePacket.getAddress() + ":" + responsePacket.getPort());
    String responseData = new String(responsePacket.getData()).trim();
    if (responseData.equals("__DISCOVERY_RESPONSE__")) { // Check valid command
        System.out.println("Found buddy!" + responsePacket.getAddress() + ":" + responsePacket.getPort());
    }
}

Конечно, следует поместить этот код в цикл в потоке. На основе этого примера: https://demey.io/network-discovery-using-udp-broadcast/

ОБНОВИТЬ

Ссылка выше мертва. Но тот же метод описан здесь: https://www.baeldung.com/java-broadcast-multicast

person user12043    schedule 24.07.2018
comment
Ссылка, которую вы предоставили в конце своего ответа, не работает, вставьте новую ссылку или приведите пример с сайта и поместите его в свой ответ. - person TwentyCharMax; 21.02.2019
comment
@Alex, спасибо за предупреждение. Добавлена ​​новая ссылка включает аналогичный код - person user12043; 01.03.2019