coding UDP communication in JavaFx - java

I have trouble coding UDP communication in JavaFx.
The code is capable of sending message but is not capable of receiving message.
What I should revise in the source code to receive the message?
Here is the source code:
public class JavaFXApplication10 extends Application {
public DatagramSocket receivesocket;
public DatagramPacket receivepacket;
public DatagramSocket sendsocket;
public DatagramPacket sendpacket;
public InetSocketAddress remoteAdress;
public Label label_IP;
public TextField tx_IP;
public Label label_SENDPORT;
public Label label_RECEIVEPORT;
public TextField tx_SENDPORT;
public TextField tx_RECEIVEPORT;
public Button bt_co;
public Button bt_start ;
private String message;
private XYChart.Series series;
private Timeline timer;
private static String IP = "192.168.121.23";
private static Integer SENDPORT = 12345;
private static Integer RECEIVEPORT = 12345;
public double time_counter=0.0;
private String text;
private byte[] b;
#Override
public void start(Stage stage) throws Exception{
/* text */
tx_IP = TextFieldBuilder.create().text(IP).build();
/* text */
tx_SENDPORT = TextFieldBuilder.create().text(""+SENDPORT).build();
/* text */
tx_RECEIVEPORT = TextFieldBuilder.create().text(""+RECEIVEPORT).build();
/*button */
bt_co = ButtonBuilder.create().text("Connection")
.prefWidth(200)
.alignment(Pos.CENTER)
.id("connect")
.build();
/* button_start */
bt_start = ButtonBuilder.create().text("START")
.id("start")
.build();
/* timer */
timer = new Timeline(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>(){
#Override
public void handle(ActionEvent event) {
time_counter = time_counter+1; // time
}
}));
timer.setCycleCount(Timeline.INDEFINITE);
timer.play();
/*figure*/
stage.setTitle("Line Chart Sample");
final NumberAxis xAxis = new NumberAxis();
final NumberAxis yAxis = new NumberAxis();
xAxis.setLabel("Time [s]");
yAxis.setLabel("Force [N]");
//creating the chart
final LineChart<Number,Number> lineChart =
new LineChart<Number,Number>(xAxis,yAxis);
lineChart.setTitle("");
//defining a series
series = new XYChart.Series();
series.setName("Force");
series.getData().add(new XYChart.Data(0.0,0.0));
lineChart.getData().add(series);
HBox root1 = HBoxBuilder.create().spacing(100).children(tx_IP ,tx_SENDPORT,tx_RECEIVEPORT).build();
HBox root2 = HBoxBuilder.create().spacing(50).children(bt_co).build();
HBox root3 = HBoxBuilder.create().spacing(25).children(bt_start).build();
VBox root4 = VBoxBuilder.create().spacing(25).children(root1,root2,root3,lineChart).build();
Scene scene = new Scene(root4);
recieve_UDP();
scene.addEventHandler(ActionEvent.ACTION,actionHandler);
stage = StageBuilder.create().width(640).height(640).scene(scene).title(" ").build();
stage.show();
}
private void recieve_UDP() throws SocketException, IOException {
ScheduledService<Boolean> ss = new ScheduledService<Boolean>()
{
#Override
protected Task<Boolean> createTask()
{
Task<Boolean> task = new Task<Boolean>()
{
#Override
protected Boolean call() throws Exception
{
receivesocket = null;
byte[] receiveBuffer = new byte[1024];
receivepacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
receivesocket = new DatagramSocket(RECEIVEPORT);
receivesocket.receive(receivepacket);
message = new String(receivepacket.getData(),0, receivepacket.getLength());
System.out.println(message);
receivesocket.close();
return true;
};
};
return task;
}
};
ss.start();
}
EventHandler<ActionEvent> actionHandler = new EventHandler<ActionEvent>(){
public void handle (ActionEvent e){
//////////////////////////////////////////////////////////////////////////////
Button src =(Button)e.getTarget();
text = src.getId();
System.out.println(text);
b = new byte[5];
if(text == "connect"){
String text_IP = tx_IP.getText();
label_IP.setText(text_IP);
IP = text_IP;
String text_SENDPORT = tx_SENDPORT.getText();
label_SENDPORT.setText(text_SENDPORT);
SENDPORT = Integer.parseInt( text_SENDPORT);
String text_RECEIVEPORT = tx_RECEIVEPORT.getText();
label_RECEIVEPORT.setText(text_RECEIVEPORT);
RECEIVEPORT = Integer.parseInt(text_RECEIVEPORT);
}
else{
remoteAdress = new InetSocketAddress(IP, SENDPORT);
sendsocket = null;
try {
sendsocket = new DatagramSocket();
} catch (SocketException ex) {
Logger.getLogger(JavaFXApplication10.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(text=="start"){
b[0] = (byte)0x02;
text ="OK";
}
else{
}
Send_UDP();
///////////////////////////////////////////////////////
}
};
public void Send_UDP(){
///////////////////////////////////////////////////////
if(text=="OK"){
sendpacket = new DatagramPacket(b, b.length,remoteAdress);
try {
sendsocket.send(sendpacket);
} catch (IOException ex) {
Logger.getLogger(JavaFXApplication10.class.getName()).log(Level.SEVERE, null, ex);
}
sendsocket.close();
text="";
}
else {}
///////////////////////////////////////////////////////
}
public static void main(String[] args) {
launch(args);
}
}

You code is really fuzzy, maybe I don't understand the purpose of all those code blocks but I can tell you UDP communication is pretty simple, let me first throw some quick light on way UDP communication works:
UDP communication refresher
Please note that I have used only some code snippets below for demonstration so kindly do not look then for completeness, complete code can be found in the code I have pasted in end.
UDP can be used for unicast as well as multicast communication. If UDP is used for unicast communication then there will always be a UDP client requesting something from a UDP server, however if UDP is used for multicast communication then UDP server will multicast/broadcast the message to all listening UDP clients.
(I will now talk more about UDP unicast) A UDP server will be listening on a network port for client requests DatagramSocket socket = new DatagramSocket(8002); socket.receive(packet);
A UDP client want to communicate with a UDP server, so it opens a DatagramSocket and send a DatagramPacket over it. DatagramPacket will contain the endpoints of the UDP server.
Once UDP client has sent the message using socket.send(packet);, it will then prepare to receive for the response from UDP server, using socket.receive(packet); (I think this where you are missing) Most important thing to understand is that if client doesn't prepare for receiving then it will not be able to get what UDP server would send because in case of UDP there is no connection between UDP client and UDP server, so UDP must be listening after sending the message.
UDP server will receive the request from UDP client, will process the request and will send using sendingDatagramSocket.send(packet);. It will prepare the DatagramPacket using the response and endpoints of the UDP client.
UDP client which is listening, as mentioned in above step socket.receive(packet); will get the response from UDP server. Important thing to note here is that if UDP client is not listening OR not listening on same port which it has opened while making the request (basically using the same DatagramSocket object used for sending the request) then UDP client will never receive whatever UDP server is going to send.
Answer to OP's questions
Main issue is that in Send_UDP you are only sending but not receiving and in recieve_UDP you are only receiving but not sending.
So, basically you need to both send and receive in UDP client and UDP server, its just that it would be vice-versa but you need to do both the things.
Sample UDP server and UDP client
UDP client:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;
public class SimpleUDPClient {
public static void main(String[] args) throws IOException {
// get a datagram socket
DatagramSocket socket = new DatagramSocket();
System.out.println("### socket.getLocalPort():" + socket.getLocalPort() + " | socket.getPort(): " + socket.getPort());
// send request
byte[] buf = "Hello, I am UDP client".getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 8002);
socket.send(packet);
// get response
packet = new DatagramPacket(buf, buf.length);
System.out.println("Waiting to receive response from server." + new Date());
socket.receive(packet);
System.out.println("Got the response back from server." + new Date());
// display response
String received = new String(packet.getData());
System.out.println("Quote of the Moment: " + received);
socket.close();
}
}
UDP server:
import java.io.*;
import java.net.*;
import java.util.*;
public class SimpleUDPServer {
public static void main(String[] args) throws SocketException, InterruptedException {
DatagramSocket socket = new DatagramSocket(8002);
while (true) {
try {
byte[] buf = new byte[256];
// receive request
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
System.out.println("### socket.getLocalPort():" + socket.getLocalPort() + " | socket.getPort(): " + socket.getPort());
// figure out response
String dString = "Server is responding: asd asdd";
buf = new byte[256];
buf = dString.getBytes();
// send the response to the client at "address" and "port"
InetAddress address = packet.getAddress();
int port = packet.getPort();
System.out.println("Data from client: " + new String(packet.getData()));
packet = new DatagramPacket(dString.getBytes(), dString.getBytes().length, address, port);
System.out.println("### Sending for packet.hashCode(): " + packet.hashCode() + " | packet.getPort(): " + packet.getPort());
//Thread.sleep(5000);
System.out.println("Now sending the response back to UDP client.");
DatagramSocket sendingDatagramSocket = new DatagramSocket();
sendingDatagramSocket.send(packet);
sendingDatagramSocket.close();
System.out.println("I am done");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Further readings
I strongly recommend read this Java tutorial, if not complete then at-least "Writing a Datagram Client and Server" section.

Related

send and recieve Socket Datagram

I am doing a server and client socket datagram.
The client connects to the server and you need to write in the client a string that contains Hello or hello.
When the server detects a string with hello or Hello, repplies to the client with another string.
The problem is that the client doesn't read the string that the server sends.
Here is my code.
Client
public class Client {
public static void main(String[] args) {
try {
System.out.println("Creando socket datagram");
DatagramSocket datagramSocket = new DatagramSocket();
Scanner myObj = new Scanner(System.in); // Create a Scanner object
System.out.println("Say Hello");
String saludo = myObj.nextLine();
System.out.println("Sending message");
InetAddress addr = InetAddress.getByName("localhost");
DatagramPacket datagrama = new DatagramPacket(saludo.getBytes(), saludo.getBytes().length, addr, 5555);
datagramSocket.send(datagrama);
System.out.println("Message sent");
System.out.println("Reading message");
byte[] mensaje = new byte[25];
DatagramPacket datagrama1 = new DatagramPacket(mensaje, 25);
datagramSocket.receive(datagrama1);
System.out.println("Message recieved: " + new String(mensaje));
System.out.println("Closing");
datagramSocket.close();
System.out.println("FInished");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server
public class Server {
public static void main(String[] args) throws InterruptedException {
try {
for (;;) {
System.out.println("Creating socket datagram");
InetSocketAddress addr = new InetSocketAddress("localhost", 5555);
DatagramSocket datagramSocket = new DatagramSocket(addr);
System.out.println("RReading message");
byte[] mensaje = new byte[25];
DatagramPacket datagrama1 = new DatagramPacket(mensaje, 25);
datagramSocket.receive(datagrama1);
System.out.println("Message recieved: " + new String(mensaje));
if (new String(mensaje).contains("hello") || new String(mensaje).contains("Hello")) {
String quetal = "¿Hello, how are you doing?";
System.out.println("Sending message");
TimeUnit.SECONDS.sleep(2);
DatagramPacket datagrama2 = new DatagramPacket(quetal.getBytes(), quetal.getBytes().length, addr.getAddress(),
5555);
datagramSocket.send(datagrama2);
System.out.println("Message Sent");
}
datagramSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have tried putting a sleep in the server in case the server sends the string before the client tries to read.
Many thanks for the help as always.
The client is using the parameter-less DatagramSocket() constructor to bind to a random port with which to send and receive on:
Constructs a datagram socket and binds it to any available port on the local host machine. The socket will be bound to the wildcard address, an IP address chosen by the kernel.
However, when the server receives a datagram, you are ignoring the IP and port where the datagram was actually sent from:
DatagramSocket.receive(DatagramPacket)
Receives a datagram packet from this socket. When this method returns, the DatagramPacket's buffer is filled with the data received. The datagram packet also contains the sender's IP address, and the port number on the sender's machine.
When the server is sending the reply, you are sending it back to the server itself at localhost:5555, not to the client at all.
On the server side, you need to change this:
DatagramPacket datagrama2 = new DatagramPacket(..., addr.getAddress(), 5555);
To either this:
DatagramPacket datagrama2 = new DatagramPacket(..., datagrama1.getAddress(), datagrama1.getPort());
Or to this:
DatagramPacket datagrama2 = new DatagramPacket(..., datagrama1.getSocketAddress());
On a side note, your server is also ignoring the actual length of the data that is being sent by the client. The server is receiving data using a 25-byte array, but the client may not actually be sending 25 bytes. If the client sends less than 25 bytes, you will end up with a String that contains random garbage on the end of it. And if the client sends more than 25 bytes, `receive() will truncate the data.
Try something more like this instead:
System.out.println("Reading message");
byte[] buffer = new byte[65535];
DatagramPacket datagrama1 = new DatagramPacket(buffer, buffer.length);
datagramSocket.receive(datagrama1);
String mensaje = new String(datagrama1.getData(), datagrama1.getLength());
System.out.println("Message recieved: " + mensaje);
if (mensaje.contains("hello") || mensaje.contains("Hello")) {
...
}
This was fun :)
Kindly keep in mind, the way this is coded might not be the best, however it works as you want.
The Client sends Hello, The server receives Hello, and Sends (Hello back at you).
Both then terminate. It doesnt keep on looping those 2 messages forever, but I showed you the idea.
The Server needs to act as a Client as well in order to send messages.
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class DReceiver{
public static void replyToTheClientListening() throws IOException {
DatagramSocket ds = new DatagramSocket();
String str = "hello back at you";
InetAddress ia = InetAddress.getByName("127.0.0.1");
DatagramPacket dp = new DatagramPacket(str.getBytes(), str.length(), ia, 3001);
ds.send(dp);
ds.close();
}
public static void listenToMessagesFromTheClient() throws IOException {
DatagramSocket ds = new DatagramSocket(3000);
ds.setSoTimeout(60000); //Wait 60 SECONDS for messages
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
ds.receive(dp);
String strRecv = new String(dp.getData(), 0, dp.getLength());
if("hello".equalsIgnoreCase(strRecv)) { //hello in any case
System.out.println("Received a MSG from the Client " + strRecv);
replyToTheClientListening();
}
ds.close();
}
public static void main(String[] args) throws Exception {
listenToMessagesFromTheClient();
}
}
The DSender is a Client but also needs to act as a Server (To Listen to Messages coming in from the other Server)
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class DSender{
public static void actAsAServerAndListenToMessages() throws IOException {
//Listen to Port 3001 --The Server will send to that port
DatagramSocket dsReceive = new DatagramSocket(3001);
dsReceive.setSoTimeout(60000); //Make it wait 60 SECONDS
byte[] buf = new byte[1024];
DatagramPacket dpReceive = new DatagramPacket(buf, 1024);
dsReceive.receive(dpReceive);
String strRecv = new String(dpReceive.getData(), 0, dpReceive.getLength());
System.out.println("Client -- Received a Msg back from Server --" + strRecv);
dsReceive.close();
}
public static void sendAMessageAsAClientToTheServer() throws IOException {
// Client will send a message to Port 3000 which the Server listens to.
DatagramSocket ds = new DatagramSocket();
String str = "hello";
InetAddress ia = InetAddress.getByName("127.0.0.1");
DatagramPacket dp = new DatagramPacket(str.getBytes(), str.length(), ia, 3000);
ds.send(dp);
ds.close();
}
public static void main(String[] args) throws Exception {
sendAMessageAsAClientToTheServer();
actAsAServerAndListenToMessages();
}
}
Reference :
https://www.javatpoint.com/DatagramSocket-and-DatagramPacket
I run the server, then the Client.

DatagramSocket Packets IPAddress being changed by router?

I have created a server that will be run on my desktop to send and receive messages from clients. The clients app will be run on android. As of now, both programs start up, and the client is able to send the initial connection to the server. My desktop is connected to the internet via a router, which i have port-forwarded from the router to receive the info.
The server is able to receive all messages sent by the client. However, the server is unable to respond. I did a quick check on the received packet (server side), and it says the ipaddress for the packet is the IP for my router. Does that mean i will be unable to send a response, since all of my packets will get their IP changed to the local address of the router (because of the port-forwarding)?
Ill post some code below, although im not sure it will help. Thanks very much for your comments.
Server:
public class QuoteServerThread extends Thread {
protected DatagramSocket socket = null;
DatagramPacket dgp = null;
protected boolean running = true;
ArrayList<ConnectedUser> users = new ArrayList<>();
String state;
int port;
int userId;
public QuoteServerThread(String name, String state) throws IOException {
super(name);
port = 4445;
userId = 1;
socket = new DatagramSocket(port);
this.state = state;
this.state = "listening";
System.out.println("Server Socket is now listening on port: " + port);
}
public void run() {
while (running) {
try {
byte[] buf = new byte[256];
// receive request
final DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
if(packet.getData() == null){
System.out.println(packet.getData());
return;
}
else{
System.out.println(packet.getData());
}
dgp = packet;
String message = new String(packet.getData(), 0, packet.getLength());
if(state.equals("listening")) {
if(message.contains("newUser")){
ConnectedUser newUser = new ConnectedUser(userId, socket);
users.add(newUser);
System.out.println("connected users: " + users.size());
String msg = "ID/" + userId;
InetAddress IPAddress = packet.getAddress();
int _port = packet.getPort();
System.out.println(IPAddress + "," + _port);
DatagramPacket out = new DatagramPacket(msg.getBytes(), msg.length(), IPAddress, _port);
socket.send(out);
userId++;
}
else if(message.contains("ID/")){
String receivedMessage[] = message.split("/");
System.out.println(receivedMessage[0] + ", " + receivedMessage[1] + ", " + receivedMessage[2]);
}
else{
System.out.println(message);
}
}
} catch (IOException e) {
e.printStackTrace();
running = false;
}
}
socket.close();
}
}
Client:
public class QuoteServerThread extends Thread {
protected DatagramSocket socket = null;
protected boolean running = true;
TextView chatWindow;
TextView notification;
EditText chatBox;
MainActivity ma;
ScrollView sv;
public QuoteServerThread(MainActivity ma, TextView chatWindow, EditText chatBox, ScrollView sv, TextView notification) throws IOException {
this("QuoteServerThread");
this.ma = ma;
this.chatWindow = chatWindow;
this.sv = sv;
this.chatBox = chatBox;
this.notification = notification;
}
public QuoteServerThread(String name) throws IOException {
super(name);
socket = new DatagramSocket();
}
public void run() {
while (running) {
try {
byte[] buf = new byte[256];
// receive request
final DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
if(packet.getData() == null){
System.out.println("data was null!");
return;
}
String message = new String(packet.getData(), 0, packet.getLength());
final String notif = message;
notification.post(new Runnable() {
public void run() {
notification.setText("server " + "__msg: " + notif);
}
});
if(ma.state.equals("connected")) {
final String chatText = chatWindow.getText().toString() + "\n" + "Sender: " + message;
chatWindow.post(new Runnable() {
public void run() {
chatWindow.setText(chatText);
sv.post(new Runnable() {
public void run() {
sv.fullScroll(View.FOCUS_DOWN);
chatBox.post(new Runnable() {
public void run() {
chatBox.requestFocus();
}
});
}
});
}
});
}
else if(ma.state.equals("waitingconnection")){
String msgSplit[];
if(message.contains("ID/")){
msgSplit = message.split("/");
final String id = msgSplit[1];
ma.clientID = Integer.getInteger(id);
notification.post(new Runnable() {
public void run() {
notification.setText("connected to server " + "__msg: " + id);
ma.state = "connected";
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
running = false;
}
}
socket.close();
}
}
the only issue here is the client not receiving a response. to state the problem again, I believe that the port forwarding on my router is changing the packets address to its local ipaddress (my phone is sending from mobile network). Any ideas on how I can fix this?
I think you are seeing effects of the network address translation (NAT) and port-forwarding. From the viewpoint of the android client it is communicating with your router. Then your router instead of processing messages itself offloads the processing to your server (port forwarding).
On your server you see the destination address. Since your android client is talking to your router, the destination IP address you see is that of your router.
If you want to reply, what you should to is take the source address of the datagram and send the reply back to that address. When you datagram will be passing the router with NAT it will change the source address to that of the router.
The issue above was due to code that I had running in the background. When sending a message, I was using a class called MsgSender. MsgSender, however, was creating a new socket and sending the data. After the data was sent, it closed the socket, no longer listening for a response from the server.
To fix this, I shared the socket that is left open, and send all data through the single socket, so that it can listen for any information that is returned.
Be sure that when you send information, if you need to listen for a response, you MUST listen through the socket it was sent from. If you are not needing to listen for a response from the data you will be sending, you can close the socket.

udp program not working

i tried my hands on networking and this is the first time i have understood some bit of it.i have a program with a client and server.What i want to do is that the server should send data continuously to a port and whenever there is any data in port say 2656 ,the client should read the data from that port and the data should be flushed from the port.I have created a server program and a client program but the client is not receiving any packet.I m running client and server on two different machines.
Server Program
import java.io.*;
import java.net.*;
public class Server{
public static void main(String args[]) throws Exception {
DatagramSocket dsocket = new DatagramSocket();
try {
String host = "192.168.0.15";
int count =1;
byte[] message = "Java Source and Support".getBytes();
// Get the internet address of the specified host
InetAddress address = InetAddress.getByName(host);
// Initialize a datagram packet with data and address
for(;;)
{
DatagramPacket packet = new DatagramPacket(message, message.length,
address, 2656);
// Create a datagram socket, send the packet through it, //close it.
System.out.println("Sending data"+message.toString();
dsocket.send(packet);
}
} catch (Exception e) {
System.err.println(e);
}
finally
{
dsocket.close();
}
}
}
Client program
package saturdayTest;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceive {
public static void main(String args[]) {
try {
int port = 2656;
// Create a socket to listen on the port.
DatagramSocket dsocket = new DatagramSocket(port);
byte[] buffer = new byte[2048];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
System.out.println("Waiting for a packer");
dsocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
System.out.println(packet.getAddress().getHostName() + ": "
+ msg);
packet.setLength(buffer.length);
}
} catch (Exception e) {
System.err.println(e);
}
}
}

Multicast server receive the same data it sends

I'm trying to allow clients that connect to my UDP server to send packets to the server, I have a server running so packets can be sent to the clients, but trying to send packets back via the client to the server seems to create some weird errors.
If I start the server, then open a client, the client will receive the first packet from the server, the client then tries to send the packet to the server, this is received by the server, but then the client throws this error
Exception in thread "main" java.lang.NumberFormatException: For input string: "testing"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at Pong.PongUDPClient.main(PongUDPClient.java:71)
Line 71 will be pointed at in the code
The server console is just printing out the data it should be sending to the client,
Here is the whole code for the server
package Pong;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.Socket;
//This is the actual server
public class PongUDPServerThread extends Thread {
//speed to send data
private long dataSpeed = 10;
private int port = 4447;
private int idPlayer = 0;
private PongModel model;
private PongView view;
private PongPlayerThread players[] = new PongPlayerThread[2];
private MulticastSocket socket = null;
private InetAddress group;
private DatagramPacket packet = null;
private int ID = 1;
public PongUDPServerThread() throws IOException
{
super("PongUDPServerThread");
}
public String rtnInfo()
{
String str;
str = model.getBall().getX() + ":" +
model.getBall().getY() + ":" +
model.getBats()[0].getX() + ":" +
model.getBats()[0].getY() + ":" +
model.getBats()[1].getX() + ":" +
model.getBats()[1].getY();
return str;
}
public void setupPong() throws IOException
{
System.out.println("Pong");
model = new PongModel();
view = new PongView();
new PongController( model, view );
model.addObserver( view ); // Add observer to the model
//view.setVisible(true); // Display Screen
model.makeActiveObject(); // Start play
//start server
socket = new MulticastSocket(port);
InetAddress group = InetAddress.getByName("230.0.0.1");
socket.setReuseAddress(true);
socket.joinGroup(group);
//socket.setReuseAddress(true);
//Inform server user
System.out.println("Server is running");
}
public void run()
{
//Server loop
while(true)
{
//Receive the data
try
{
byte[] receiveBuf = new byte[256];
packet = new DatagramPacket(receiveBuf, receiveBuf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println(received);
}
catch (IOException e)
{
}
try
{
byte[] buf = new byte[256];
//Gather data
buf = rtnInfo().getBytes();
//System.out.println(buf.toString());
//Send data
packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("230.0.0.1"), port);
socket.send(packet);
//Sleep the server
try
{
sleep((long)dataSpeed);
}
catch (InterruptedException e)
{
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
//socket.close();
}
}
Here is the client code
package Pong;
import java.io.*;
import java.net.*;
import java.util.*;
public class PongUDPClient {
private static int port = 4447;
public static void main(String[] args) throws IOException
{
//Setup pong rdy
PongModel model = new PongModel();
PongView view = new PongView();
new PongController( model, view );
model.addObserver( view ); // Add observer to the model
String pos;
model.makeActiveObject(); // Start play
//model.clientModel();
MulticastSocket socket = new MulticastSocket(port);
//socket.setReuseAddress(true);
InetAddress address = InetAddress.getByName("230.0.0.1");
//Join the UDP list port
socket.setReuseAddress(true);
socket.joinGroup(address);
DatagramPacket packet;
view.setVisible(true); // Display Screen
System.out.println("Connected");
//Id is sent here.
while(true)
{
//Send data to server
try
{
byte[] receiveBuf = new byte[256];
//Gather data
receiveBuf = "testing".getBytes();
//System.out.println(buf.toString());
//Send data
packet = new DatagramPacket(receiveBuf, receiveBuf.length, InetAddress.getByName("230.0.0.1"), port);
socket.send(packet);
//Sleep the server
}
catch (IOException e)
{
e.printStackTrace();
}
byte[] buf = new byte[256];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
//System.out.println("Server data: " + received);
String[] posValues = received.split(":");
model.getBall().setX(Double.parseDouble(posValues[0])); // <-- Line 71
model.getBall().setY(Double.parseDouble(posValues[1]));
model.getBats()[0].setX(Double.parseDouble(posValues[2]));
model.getBats()[0].setY(Double.parseDouble(posValues[3]));
model.getBats()[1].setX(Double.parseDouble(posValues[4]));
model.getBats()[1].setY(Double.parseDouble(posValues[5]));
//Check for keyboard input
if(PongController.moveUp == true && PongController.moveDown == false)
{
System.out.println("Up");
PongController.moveUp = false;
}
else if(PongController.moveUp == false && PongController.moveDown == true)
{
System.out.println("Down");
PongController.moveDown = false;
}
else
{
//serverOut.println("nothing");
}
}
}
}
Been stuck on this for awhile, and can't seem to find any tutorials on how to send packets from client to server using Multicast.
You are experiencing multicast loopback. Turn it off with MulticastSocket#setLoopbackMode(true), or, if that peer is just sending to the multicast group, not receiving, it doesn't need to join the group at all.

Implementing a simple UDP network that continuously broadcasts to its neighbours

I have 3 nodes A, B and C with their respective port numbers.
I'm trying to write a java program that takes in 3 arguments:
its node name and its 2 neighboring node's ports and broadcasts a string "Hello I'm A" to them (so A would broadcast to B and C). It will do this every 3 seconds.
This program will be run in 3 separate instances.
Upon receiving a string it will print what node it has received it from "Received string" (example for Port B).
I have difficulties implementing this, I have heard of something called multicasting with UDP though. Here is my work so far, what am I doing wrong?
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) { }
}
}
}
I know I'm close to the solution. I'm able to broadcast properly but it's the constantly listening part that gets me.
I think its best to use a separate Thread to listen for data on your own port.
A sends data to B and blocks until it gets a packet from B.
B sends data to C and blocks until it gets a packet from C.
C sends data to A and blocks until it gets a packet from A.
Every node is waiting for each other. Just send the packets and wait 3 seconds.
The other thread is going to listen only.
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);
}
}
Here is a simple frame for a server with two threads, one writing and one reading, place your network code at the right places.
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();
}
}

Categories

Resources