Я создаю приложение для связи клиент-сервер и хотел бы, чтобы клиент мог автоматически обнаруживать и подключаться к серверу, учитывая, что они находятся в одной сети.
Раньше мой код работал на машинах с Linux и Windows. Я бы транслировал простое сообщение, и его можно было бы прочитать. Я также мог видеть это сообщение при просмотре сетевого трафика с помощью Wireshark.
Подход, который я использую, заключается в том, чтобы
- Получите широковещательный адрес(а) в сети на сервере.
- В течение заданного времени транслируйте сообщение (скоро будет IP-адрес сервера)
- На стороне клиента дождитесь получения сообщения.
Я новичок в работе с сетями, поэтому любые очевидные ошибки могут быть не очевидны для меня сразу.
Код трансляции сервера:
public class Broadcaster {
/* ... */
public void pulse() throws InterruptedException, IOException, SocketException {
Long elapsed = new Date().getTime();
Long timeout = elapsed + this.duration;
DatagramPacket packet = new DatagramPacket(this.message.getBytes(), this.message.length());
HashSet<InetAddress> channels = Broadcaster.getBroadcastChannels();
while(elapsed <= timeout) {
for(InetAddress channel : channels) {
DatagramSocket socket = new DatagramSocket(this.port);
socket.setBroadcast(true);
socket.connect(channel, this.port);
socket.send(packet);
System.out.println("Broadcast sent to " + channel.getHostAddress() + " (" + socket.getPort() + "): " + this.message);
socket.close();
}
Thread.sleep(this.frequency);
elapsed = new Date().getTime();
}
}
private static HashSet<InetAddress> getBroadcastChannels() throws SocketException {
/* Returns 192.168.0.255 */
}
public static void main(String[] args) {
Broadcaster heart = new Broadcaster("Hello from the Raspberry Pi!", 120000, 5000, 8027);
try {
heart.pulse();
} catch(SocketException e) {
/* ...etc... */
} finally {
System.out.println("Broadcasting completed.");
}
}
}
Код клиента:
public class BroadcastListener {
private int port;
private int length;
public BroadcastListener(int length, int port) {
this.port = port;
this.length = length;
}
public String getNext() throws IOException {
byte buffer[] = new byte[this.length];
DatagramSocket socket = new DatagramSocket(this.port);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Waiting on " + socket.getLocalSocketAddress());
socket.receive(packet);
socket.close();
return new String(buffer);
}
public static void main(String[] args) {
System.out.println("Listening for network broadcasts...");
BroadcastListener broadcast = new BroadcastListener(128, 8027);
try {
System.out.println("Received broadcast: " + broadcast.getNext());
} catch(IOException e) {
System.out.println("Could not receive broadcasts:");
System.out.println(e.getMessage());
}
}
}
Адрес широковещательной рассылки/маски сети, отображаемый на обоих устройствах ifconfig
, равен netmask 255.255.255.0 broadcast 192.168.0.255
.
Что меня больше всего смущает, так это то, что Wireshark все еще видит трансляцию, но когда я запускаю клиентскую программу Java, она просто сидит на socket.receive(packet);
И клиент, и сервер подключены к порту 8027. Понятно, что вещатель работает, но прослушиватель клиентского вещания — нет. Кто-нибудь знает, что может происходить? Спасибо!