Java UDP multicasting - strange exception - java

I'm using the following code to send Hello, world! to a multicast group with Java.
InetSocketAddress sa = new InetSocketAddress("239.0.0.1", 12345);
MulticastSocket s = new MulticastSocket(sa);
s.setTimeToLive(255);
s.joinGroup(sa.getAddress());
byte[] sbuf = "Hello, world!".getBytes();
DatagramPacket sp = new DatagramPacket(sbuf, sbuf.length, sa);
s.send(sp);
byte[] rbuf = new byte[1024];
DatagramPacket rp = new DatagramPacket(rbuf, rbuf.length);
s.receive(rp);
System.out.format("Received \"%s\".\n", new String(rbuf));
s.leaveGroup(sa.getAddress());
s.close();
For some reason, the code always throws an exception like this:
java.io.Exception: Invalid argument
at java.net.PlainDatagramSocketImpl.send(Native Method)
at java.net.DatagramSocket.send(...)
at ...
Why is this? How can I fix it?

To get data:
InetAddress group;
int port;
group = InetAddress.getByName("239.0.0.1");
port = Integer.parseInt("12345");
//create Multicast socket to to pretending group
MulticastSocket s = new MulticastSocket(port);
s.joinGroup(group);
while(running){
s.receive(pkt);
System.out.println();
String msg_rec;
msg_rec = new String(pkt.getData(), 0, pkt.getLength());
System.out.println("(FROM:" + pkt.getAddress()+ ") "+ msg_rec);
System.out.println();
}
To send data:
String msgToSend = "Hello, world!";
dgram = new DatagramPacket(msgToSend.getBytes(), msgToSend.length(), group ,port);
s.send(dgram);

You are calling send() on an unconnected DatagramSocket with a DatagramPacket that doesn't contain a destination address:port. So there is nowhere to send it to. If you mean to send to the multicast address, you need to say so, by doing either of he things mentioned in the first sentence. Joining the group doesn't do that: it only affects receiving.

Related

May UDP group the sending of datagrams?

With UDP, if I send two DatagramPackets on one DatagramSocket (let's say first datagram say "ABCD" and the second say "EFGH"),
is it theorically possible that my first call to "receive" on the socket give me a DatagramPacket containing "ABCDEFGH"?
In other words, does messages sent with UDP can be grouped into one message and if so, does UDP "remembers" it was several distincts messages in the first place?
Let's assume my client is :
//DSender.java
import java.net.*;
public class DSender{
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket();
InetAddress ip = InetAddress.getByName("127.0.0.1");
// Send a first message
String str = "ABCD";
DatagramPacket dp1 = new DatagramPacket(str.getBytes(), str.length(), ip, 3000);
ds.send(dp1);
// Send a second message (on the same socket)
str = "EFGH";
DatagramPacket dp2 = new DatagramPacket(str.getBytes(), str.length(), ip, 3000);
ds.send(dp2);
ds.close();
}
}
And my server is:
//DReceiver.java
import java.net.*;
public class DReceiver{
public static void main(String[] args) throws Exception {
DatagramSocket ds = new DatagramSocket(3000);
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, 1024);
ds.receive(dp);
String str = new String(dp.getData(), 0, dp.getLength());
System.out.println(str);
ds.close();
}
}
This code may output "ABCD", it may also output "EFGH" (if first message is lost), it may also output nothing at all (if both messages are lost), but can it output "ABCDEFH"?
No. UDP datagrams are received intact and entire, or not at all. Also possibly multiple times, out of order, ... but never coalesced.

How to properly compare string values received from datagram packets?

I'm making a simple client server program. When the client sends the string "start", I want the server to start executing some code. Right now, I have the client sending a datagram packet with the message "start", the server gets the byte buffer from the packet, turns it into a string, and then compares that string value with the string literal "start". Obviously I'm doing something wrong because my code never enters the for loop of if(sentence.equals(start){ System.out.println("ok");}
My code:
public static void main(String args[]) throws IOException{
byte[] receiveData;
byte[] sendData;
DatagramSocket serverSocket = new DatagramSocket(2014);
while(true){
receiveData = new byte[15];
DatagramPacket frame = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(frame);
InetAddress IPaddress = frame.getAddress();
System.out.println("INET " + IPaddress);
byte[] data;
int port = frame.getPort();
System.out.println("port " + port);
String sentence = new String(frame.getData());
String start = new String("start");
System.out.println("RECEIVED FROM CLIENT: " + sentence);
if(sentence.equals(start)){
System.out.println("ok");
}
}
}
Make the following change.
String sentence = new String(frame.getData(), 0, frame.getLength());

Udp how to get integer from the server?

i shall implement a UDP-based client/server application and im new in the world of Java. The Server implements a simple request-acknowledge protocol upon the UDP protocol. For a received string identifier (command) with optional parameters the server returns a specified result. For example "thread" returns a random integer number between 1 and 5 and length returns a random integer number between 5 and 25.
The questions is did i do the implementation right and how can i fix my problem (length nr is always between 1 and 5). I think my problem is that in the server class the if statements are not checked. Is there some other way to send a comand to a server i tried here to do it with sending strings then trying to check it with if statements?
and thats my code (Server):
public class server {
public static void main(String[] args) throws IOException, InterruptedException {
DatagramSocket skt;
try {
skt = new DatagramSocket(1252);
byte [] buffer = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
skt.receive(request);
String arrayMsg = new String(request.getData());
System.out.println(arrayMsg);
//check if the client asks for threadnr
if(arrayMsg.equals("thread")){
int threadnumber = (int) (Math.random()*5)+1;
String threadnum = Integer.toString(threadnumber);
byte [] b = threadnum.getBytes();
DatagramPacket reply = new DatagramPacket(b, b.length, request.getAddress(), request.getPort());
skt.send(reply);;}
//check if the client asks for lengthnr
else if(arrayMsg.equals("length")){
int lengthnumber = (int) (Math.random()*25)+5;
String lengthnum = Integer.toString(lengthnumber);
byte [] b = lengthnum.getBytes();
DatagramPacket reply = new DatagramPacket(b, b.length,request.getAddress(), request.getPort());
skt.send(reply);}
}}
catch (SocketException e) {
System.out.println("UDP Port 9876 is occupied.");
System.exit(1);
}}}
thats my Client:
public class client {
public static void main(String[] args) throws UnknownHostException, IOException {
DatagramSocket skt = new DatagramSocket();
InetAddress host = InetAddress.getByName("localhost");
int serverSocket = 1252;
byte [] senddata = new byte [1000];
byte [] getdata = new byte[1000];
//thread send request
String th = "thread";
senddata = th.getBytes();
DatagramPacket requestth = new DatagramPacket(senddata, senddata.length, host, serverSocket);
skt.send(requestth);
//thread get reply
DatagramPacket replyth = new DatagramPacket ( getdata, getdata.length);
skt.receive(replyth);
String arrayth = new String(replyth.getData());
int threadnr=Integer.parseInt(arrayth.trim()); //convert thread string to int and trim it (whitespace)
System.out.println("Thread received " + threadnr);
//length send request
String lg = "length";
senddata = lg.getBytes();
DatagramPacket requestlg = new DatagramPacket(senddata, senddata.length, host, serverSocket);
skt.send(requestlg);
//length get reply
DatagramPacket replylg = new DatagramPacket ( getdata, getdata.length);
skt.receive(replylg);
String arraylg = new String(replyth.getData());
int lengthnr=Integer.parseInt(arraylg.trim()); //convert thread string to int and trim it (whitespace)
System.out.println("Length received " + lengthnr);
skt.close();
And all i get is something like this:
Thread received 3
Length received 1
(Length should be between 5 and 25 and in my case its never bigger then 5)
The code parses the response from the first message instead of from the last, so you get the random 1-5. I suggest using better names for the variables and you'll spot the problem quicker.

DatagramSocket fails on Android with 'Try Again'

I am trying to send DatagramPackets (UDP) in my Android application:
//create a byte to receive data
mClientSocket = new DatagramSocket();
byte[] receiveData = new byte[MAX_RECEIVE_DATA_SIZE_BYTES];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
// Set a receive timeout
mClientSocket.setSoTimeout(timeout);
// receive the packet
mClientSocket.receive(receivePacket);
return new String(receivePacket.getData(), 0,
receivePacket.getLength());
I get the following error:
Try again
Am I missing something here?
Well to send the UDP you'd need something similar to:
Server:
String messageStr="Hello Android!";
int server_port = 12345;
DatagramSocket s = new DatagramSocket ();
InetAddress local = InetAddress .getByName("192.168.1.102");
int msg_length=messageStr.length();
byte[] message = messageStr.getBytes();
DatagramPacket p = new DatagramPacket (message, msg_length,local,server_port);
s.send(p);
Client:
String text;
int server_port = 12345;
byte[] message = new byte[1500];
DatagramPacket p = new DatagramPacket (message, message.length);
DatagramSocket s = new DatagramSocket (server_port);
s.receive(p);
text = new String (message, 0, p.getLength());
Log.d("Udp tutorial","message:" + text);
s.close();
References:
Simple UDP communication example

DatagramPacket not transmitting the right message

I'm implementing a client/server application using UDP transmissions. Here is my part of my code :
Client :
InetAddress serverAddress = ...
int serverPort = ...
DatagramSocket socket = new DatagramSocket(9999);
...
String message = "<HELLO>";
byte[] outbuffer = new byte[1000];
outbuffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(outbuffer, outbuffer.length, serverAddress, serverPort);
socket.send(this.packet);
Server :
DatagramSocket serverSocket = new DatagramSocket(9876);
...
byte[] inbuffer = new byte[1000];
DatagramPacket packet = new DatagramPacket(inbuffer, inbuffer.length);
serverSocket.receive(packet);
String response = new String(packet.getData(), 0, packet.getLength());
System.out.println(response);
if("<HELLO>".equals(response)){
System.out.println("OK");
} else {
System.out.println("ERROR");
}
My problem is the following: if I print the response String on the client side that is comming from the client, everything looks fine ("").
But for some reasons when I trie to compare the response coming from the server using .equals or a RegExp it fails !
May be it's related to String encoding but I don't know where and why it fails. Both client and server are running on the same host right now, so it might not be related to JVM differences.
You're currently using the platform default encoding to both encode and decode strings. You should absolutely not do that. Specify the encoding both in the getBytes() call and the constructor call, e.g.
byte[] outBuffer = message.getBytes("UTF-8");
Also note that your current code creates a byte array of length 1000 and then immediately throws it away:
byte[] outbuffer = new byte[1000];
// Byte array created on previous line is now useless!
outbuffer = message.getBytes();
... don't do that.
We can't really tell much more from the code you've given us - if you could produce short but complete programs demonstrating the problem, that would really help.
For debugging, I would suggest you log the contents of the datagram packet you receive, while still in binary. Presumably it's not what you expected, but that doesn't help to show what it was.
EDIT: Here's a pair of short but complete programs which do work:
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception{
DatagramSocket socket = new DatagramSocket(9999);
byte[] inbuffer = new byte[1000];
DatagramPacket packet = new DatagramPacket(inbuffer, inbuffer.length);
socket.receive(packet);
String response = new String(packet.getData(), 0,
packet.getLength(), "UTF-8");
System.out.println(response);
if("<HELLO>".equals(response)){
System.out.println("OK");
} else {
System.out.println("ERROR");
}
}
}
// Client.java
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
byte[] output = "<HELLO>".getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(output, output.length,
InetAddress.getLocalHost(),
9999);
socket.send(packet);
}
}
You have a variable response and reponse.
I am assuming that they won't be the same and your test should fail.
This is the sort of thing you should be able to see in a debugger.

Categories