MulticastSocket receives message twice - java

I send messages to WIFI Access Point via MulticastSocket and get replies always twice. If I try to send message to me self, I get message twice again. This is my receiver code:
protected Void doInBackground(Void... params) {
String lText;
byte[] lMsg = new byte[GlobalConfig.MAX_UDP_DATAGRAM_LEN];
DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
MulticastSocket ds = null;
try {
ds = new MulticastSocket (32001);
InetAddress serverAddr = InetAddress.getByName("224.237.124.120");
ds.joinGroup(serverAddr);
while (serverActive) {
ds.receive(dp);
Log.d("UDP packet received", dp.toString());
lText = new String(lMsg, 0, dp.getLength());
receivedMessage = lText;
doSomething();
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null) {
ds.close();
}
}
return null;
}
I tried to send via DatagramSocket and via MulticastSocket - no matter. I get messages alway twice. I don't understand why!
EDIT: my LogCat:
I/GatewayController﹕ Message Sent
...
D/UDP packet received﹕ java.net.DatagramPacket#422dc860
D/UDP packet received﹕ java.net.DatagramPacket#422dc860
EDIT2: Sender code
protected Void doInBackground(Void... params) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
InetAddress serverAddr = InetAddress.getByName("224.237.124.120");
DatagramPacket dp;
dp = new DatagramPacket(byteMsg, byteMsg.length,
serverAddr, 32000);
ds.send(dp);

I tried to send via DatagramSocket and via MulticastSocket - no matter. I get messages alway twice. I don't understand why!
EDIT: my LogCat:
I/GatewayController﹕ Message Sent ...
D/UDP packet received﹕ java.net.DatagramPacket#422dc860 D/UDP packet received﹕ java.net.DatagramPacket#422dc860
This is not evidence that you received the same message twice. It is evidence that you always receive into the same byte array. Try logging the message content.
However multicast is UDP, and UDP does not guarantee delivery, or single delivery, or sequenced delivery, so it remains possible you will get duplicates. If that's semantically important, you need to detect it via sequence numbers.

Here is the right way:
InetAddress group = InetAddress.getByName(GlobalConfig.MULTICAST_IP);
SocketAddress sockaddr = new InetSocketAddress(group,GlobalConfig.LOCAL_PORT);
ds = new MulticastSocket(sockaddr);
ds.joinGroup(group);
This is important, but difficult to find in examples in Internet:
SocketAddress sockaddr = new InetSocketAddress(group,GlobalConfig.LOCAL_PORT);
ds = new MulticastSocket(sockaddr);

Related

When we receive packets from an UDP server, why do we have to receive them in a seperate thread?

So my application is a very simple. If you type something through the scanner it sends it over to the server, the server sends it back to client. However, i don't understand why we have to put our code where we handle our receiving packets from the server into a thread?
The code below works fine but if i don't use use multithreading then the application doesn't work. The part where i send packets also stop working. Could you explain why this happens?
public class Client {
private static DatagramSocket socket = null;
public static void main(String[] args) {
System.out.println("Send to server:");
Scanner scanner = new Scanner(System.in);
while (true) {
try {
// port shoudn't be the same as in TCP but the port in the datagram packet must
// be the same!
socket = new DatagramSocket();
} catch (SocketException e1) {
System.out.println("[CLIENT] Unable to initiate DatagramSocket");
}
InetAddress ip = null;
try {
ip = InetAddress.getByName("127.0.0.1");
} catch (UnknownHostException e) {
System.out.println("[CLIENT] Unable to determine server IP");
}
// must be in a while loop so we can continuously send messages to server
String message = null;
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
receive();
}
});
thread.start();
while (scanner.hasNextLine()) {
message = scanner.nextLine();
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ip, 6066);
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to send packet to server");
}
}
}
}
private static void receive() {
// receiving from server
byte[] buffer2 = new byte[100];
DatagramPacket ps = new DatagramPacket(buffer2, buffer2.length);
while (true) {
try {
socket.receive(ps);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to receive packets from server.");
}
System.out.println("[SERVER] " + new String(ps.getData()));
}
}
}
If you type something through the scanner it sends it over to the
server, the server sends it back to client.
So the main method runs on the main thread and does some job. The job that you just referenced.
Read some user input plus the following part
while (scanner.hasNextLine()) {
message = scanner.nextLine();
byte[] buffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ip, 6066);
try {
socket.send(packet);
} catch (IOException e) {
System.out.println("[CLIENT] Unable to send packet to server");
}
}
Title: receive packets from an UDP server
You want to receive packets but you don't want to block the user from typing something as input and sending it to the server.
Therefore you need to do 2 jobs simultaneously. AKA multithreading

Does a UDP connection require a server/client?

I want to send out a UDP packet/message out to another device on the same ethernet connection, but I'm not sure where a server/client relationship would be here.
The receiving message is configured to automatically send a response back upon receiving a message, so both devices would just be communicating to each other...
Am I missing something?
I'm confused because the code I used to send a message from a client to a server has parameters "server ip" and "server port" so I'm not sure if I can 1) just replace the parameters and use the same code and 2) if it's possible, what to put in those parameters, the initial device's port # and ip? Or the second device's?
Thanks!
The code snippet:
new Thread(new Runnable() {
#Override
public void run() {
try {
InetAddress SERVERIP = InetAddress.getByName(SERVER_IP);
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
byte[] msg = message.getBytes();
DatagramPacket packet = new DatagramPacket(msg, message.length(),
SERVERIP, SERVERPORT);
socket.send(packet);
socket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}).start();
I'm not entirely sure if the question you want answered is how to respond to the device that sent the message from the device that received the message.
If this is the case then the following code is a basic example of how you could respond to the initial sender device by getting the address and port from the packet that was received over the socket.
// Receive and respond thread.
new Thread(new Runnable() {
#Override
public void run() {
try {
// Receive
DatagramSocket socket = new DatagramSocket(4445);
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
// Respond
// Get sender's/return address from the packet that was received.
InetAddress address = packet.getAddress();
// Get sender's/return port from the packet that was received.
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);
socket.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}).start();
I would also recommend reading the following documentation regarding writing a datagram server and client.

UDP Packet not being recieved on localhost

Hey guys im having trouble recieving UDP packets in java. I've currently tested it on locolhost and my uni's servers. No exceptions are being thrown its just my client not recieve a single packet. Heres some code :
at line 136 in my Server calls
ps.PacketUtilSendFileLength();
// Packet Service class snippet
public void PacketUtilSendFileLength() throws IOException {
DatagramPacket packet = null;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(file_length);
buffer.flip();
if (V6_Mode) {
packet = new DatagramPacket(hash(buffer.array()), buffer.array().length, Hostv6, PORT);
} else packet = new DatagramPacket(hash(buffer.array()), buffer.array().length, Hostv4, PORT);
datagramSocket.send(packet);
}
My client which calls
ByteBuffer buffer = ByteBuffer.allocate(8);// these 2 lines are made at the start of the main
DatagramPacket FileLength_ACK = new DatagramPacket(buffer.array(),buffer.array().length);
...
ps.PacketUtilRecieve(FileLength_ACK);```
``` public DatagramPacket PacketUtilRecieve(DatagramPacket p){
try {
datagramSocket.receive(p);
return p;
} catch (IOException e) {
PacketUtilSendError();
e.printStackTrace();
}
return null;
}
my Server is sending the packet in but my client never recieves it what am i doing wrong here?
full code : https://github.com/WeStandUnited/SlidingWindow/tree/master/src

Java UDP respond to broadcast request

At work we are developing an android app that communicates with set top boxes(STB).
It all works fine but I'm trying to create a "mock" STB that the app can connect to so I can control the responses for testing.
I have no access to the code in the STB to know how they set up the sockets but I do have a simplified version of the client code used by the app.
Here's the client code:
public class UDPClient {
public static void main(String[] args) throws SocketException, UnknownHostException {
DatagramSocket c = new DatagramSocket(12345);
c.setBroadcast(true);
c.setSoTimeout(20000);
String msearchData = "DATA";
byte[] sendData = mSearchData.getBytes();
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("239.255.255.250"), 1900);
c.send(sendPacket);
System.out.println("Request packet sent");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// wait for reply
byte[] recBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recBuf, recBuf.length);
try {
c.receive(receivePacket);
System.out.println("PACKET RECEIVED!");
System.out.println(new String(receivePacket.getData()));
} catch (IOException e) {
e.printStackTrace();
}
c.close();
}
}
When I run this code on my development laptop (and I'm on a wireless network with that STB) the STB responds.
However, I have another laptop setup to pretend to be another STB on the same network(mock STB).
The "mock" STB simply refuses to pick up the broadcasts requests and I'm stuck.
Here's some code I use to act as the mock STB. I've tried various combinations of ports but nothing works.
public class MockBox {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
while (true) {
System.out.println(">>>Ready to receive broadcast packets!");
byte[] recvBuf = new byte[15000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet); // blocks
// Packet received
System.out.println(">>>Packet received from " + packet.getAddress().getHostAddress());
System.out.println(">>>Packet data: " + new String(packet.getData()));
socket.close();
}
}
}
Any help appreciated!
Disable the software firewall.
Use MulticastSocket instead of DatagramSocket. (Note: The address you specified above is a multicast address.)
Use TTL of at least 1. If that doesn't work, use 2. Repeat, but don't go above say 4 or 5 on a LAN, because at that point, you're already past reasonable. (Zero won't leave the machine. Using a value too high may cause the packet to be discarded somewhere along the route.)

MulticastSocket doesn't open port

I'm trying to create a simple multicast communication between my PC (Ubuntu, client) and my phone (Android, server).
Unicast/TCP connections work without any problem, the defined port (37659) opens both on PC and phone. When trying to use a MulticastSocket, no ports get opened. nmap tells me the specified port (36963) is a TCP port and that it is closed. (While the receive-method is being executed).
Am I doing something wrong? Or is the firewall blocking the multicast sockets? (I've tried about 20 different ports and none worked..., currently using port 36963)
EDIT: Also with the firewall completely down, nmap tells me the port is closed...
The server's code (phone):
private void multicastLoop() {
String res = Build.FINGERPRINT + "\n";
final InetAddress group;
final MulticastSocket socket;
final DatagramPacket response;
try {
group = InetAddress.getByName("224.0.0.115");
socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(10000);
socket.joinGroup(group);
response = new DatagramPacket(res.getBytes(), res.length(), group, mport);
} catch (IOException e) {
e.printStackTrace();
return;
}
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while(isRunning) {
try {
byte[] data = new byte[1024];
DatagramPacket dm = new DatagramPacket(data, data.length);
socket.receive(dm);
Log.d("udp", "received");
if (Arrays.equals(dm.getData(), "someone there".getBytes())) {
socket.send(response);
}
} catch (SocketTimeoutException e) {
continue;
} catch (IOException e) {
e.printStackTrace();
}
}
try {
socket.leaveGroup(group);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
The client's code (computer):
public String[] findServers() {
String hello = "someone there";
try {
InetAddress group = InetAddress.getByName(mhost);
MulticastSocket socket = new MulticastSocket(mport);
socket.setLoopbackMode(true);
socket.setSoTimeout(60000);
socket.joinGroup(group);
DatagramPacket p = new DatagramPacket(hello.getBytes(), hello.length(), group, mport);
byte[] buffer = new byte[1024];
socket.send(p);
DatagramPacket r = new DatagramPacket(buffer, buffer.length);
socket.receive(r);
socket.leaveGroup(group);
socket.close();
String srinfo = "";
byte[] data = r.getData();
for (byte b: data)
srinfo += (char) b;
System.out.println("Server found at " + r.getAddress().getHostName() + ": " + srinfo);
} catch (SocketTimeoutException e) {
return new String[] {"timeout"};
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Make sure mhost is set to "224.0.0.115" not some machine name.
Make sure multicast is enabled on your router.
If the host is multi-homed, you need to join the multicast group via all local interfaces, not just the default one, which is what you're doing at present.
You could send the response back to the source address it came from, which is in the received datagram packet. That would also mean that the client doesn't need a MulticastSocket, only a DatagramSocket.

Categories

Resources