- Mam 3 węzły A, B i C z odpowiednimi numerami portów.
- Próbuję napisać program w języku Java, który przyjmuje 3 argumenty: jego nazwa węzła i 2 sąsiednie porty węzła i rozgłasza do nich ciąg
"Hello I'm A"
(aby A rozgłaszał do B i C). Będzie to robić co 3 sekundy. - Ten program będzie uruchamiany w 3 oddzielnych instancjach.
- Po odebraniu ciągu wypisze, który węzeł otrzymał go z
"Received string"
(przykład dla Portu B).
Mam trudności z zaimplementowaniem tego, słyszałem jednak o czymś o nazwie multicasting
z UDP. Oto moja dotychczasowa praca, co robię źle?
class UDP {
public static void main(String[] args) throws Exception {
String nodeName = args[0];
int neighbourPort1 = Integer.valueOf(args[1]);
int neighbourPort2 = Integer.valueOf(args[2]);
while(true) {
Thread.sleep(3000); //every 3 seconds
//Continously broadcast and listen to neighbour1
DatagramSocket socket1 = null;
try {
//CREATE SOCKET TO NEIGHBOUR1
InetAddress host = InetAddress.getByName("localhost");
socket1 = new DatagramSocket();
socket1.connect(host, neighbour1);
//CREATE DATAGRAMS FOR SENDING
String message = "Hello I'm " + nodeName;
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, host, port);
socket1.send(sendPacket);
//CREATE DATAGRAMS FOR RECEIVING
byte[] receiveData = new byte[100]; //is there a way to determine the needed space?
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket1.receive(receivePacket);
System.out.println("Received string");
} catch(Exception e) { }
//Do the same for neighbour2, code is basically identical except for variables
DatagramSocket socket2 = null;
try {
//CREATE SOCKET TO NEIGHBOUR2
InetAddress host = InetAddress.getByName("localhost");
socket2 = new DatagramSocket();
socket2.connect(host, neighbour2);
//FOR SENDING DATAGRAMS
String message = "Hello I'm " + nodeName;
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, host, port);
socket2.send(sendPacket);
//FOR RECEIVING DATAGRAMS
byte[] receiveData = new byte[100]; //is there a way to determine the needed space?
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket2.receive(receivePacket);
System.out.println("Received string");
} catch(Exception e) { }
}
}
}
Wiem, że jestem blisko rozwiązania. Jestem w stanie nadawać poprawnie, ale to ta część, w której ciągle słucham, mnie dopada.
2 odpowiedzi
Myślę, że najlepiej jest użyć osobnego wątku do nasłuchiwania danych na własnym porcie.
- A wysyła dane do B i blokuje, dopóki nie otrzyma pakietu od B.
- B wysyła dane do C i blokuje, dopóki nie otrzyma pakietu z C.
- C wysyła dane do A i blokuje, dopóki nie otrzyma pakietu z A.
Każdy węzeł czeka na siebie. Po prostu wyślij pakiety i poczekaj 3 sekundy. Drugi wątek będzie tylko słuchać.
public class UDP {
public static void main(String[] args) throws Exception {
final String nodeName = args[0];
final int ownPort = Integer.valueOf(args[1]);
final int neighbourPort1 = Integer.valueOf(args[2]);
final int neighbourPort2 = Integer.valueOf(args[3]);
// Don't create a new socket every time
DatagramSocket neighbour1 = new DatagramSocket();
DatagramSocket neighbour2 = new DatagramSocket();
neighbour1.connect(InetAddress.getLocalHost(), neighbourPort1);
neighbour2.connect(InetAddress.getLocalHost(), neighbourPort2);
// You have to LISTEN
new Thread() {
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(ownPort);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
// Blocks until it gets a packet
socket.receive(packet);
System.out.println("Received string");
}
// socket.close();
} catch (final Exception e) {
e.printStackTrace();
}
}
}.start();
while (true) {
Thread.sleep(3000);
sendPacket(neighbour1, nodeName);
sendPacket(neighbour2, nodeName);
}
// If you're not using an infinite loop:
// neighbour1.close();
// neighbour2.close();
}
private static void sendPacket(DatagramSocket to, String from) throws Exception {
String message = "Hello I'm " + from;
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length);
to.send(packet);
}
}
Oto prosta ramka dla serwera z dwoma wątkami, jednym piszącym i jednym czytającym, umieść kod sieciowy we właściwych miejscach.
package testing;
import java.util.Scanner;
public class ThreadTest {
public class MyListenerThread extends Thread {
@Override
public void run() {
/*
* Open Datagram ...
*/
while (true) {
/*
* Read data ...
*/
Scanner scanner = new Scanner(System.in);
System.out.println("read: " + scanner.next());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MySenderThread extends Thread {
@Override
public void run() {
/*
* Open Multicast ...
*/
while (true) {
/*
* Send ...
*/
System.out.println("Send ...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void start() {
MyListenerThread listener = new MyListenerThread();
MySenderThread sender = new MySenderThread();
listener.start();
sender.start();
}
public static void main(String[] args) {
ThreadTest server = new ThreadTest();
server.start();
}
}
Podobne pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].