Multicast in java - java

I am trying to write a simple multicast trial.
I used a standard code (sender and reciever).
I tried a few different standard pieces of code. it appears that the receiving code is stuck on receive (as if it's not receving anything).
receive side:
byte[] b = new byte[3];
DatagramPacket dgram = new DatagramPacket(b, b.length);
MulticastSocket socket =
new MulticastSocket(4545); // must bind receive side
socket.joinGroup(InetAddress.getByName("226.100.100.125"));
while(true) {
socket.receive(dgram); // blocks until a datagram is received
System.err.println("Received " + dgram.getLength() +
" bytes from " + dgram.getAddress());
dgram.setLength(b.length); // must reset length field!
}
sending side:
DatagramSocket socket = new DatagramSocket();
byte[] b = new byte[]{(byte)1,(byte)5,(byte)3};
DatagramPacket dgram;
dgram = new DatagramPacket(b, b.length,
InetAddress.getByName("226.100.100.125"), 4545);
System.err.println("Sending " + b.length + " bytes to " +
dgram.getAddress() + ':' + dgram.getPort());
while(true) {
System.err.print(".");
socket.send(dgram);
Thread.sleep(1000);
}
What is wrong with my code?
*I tried alot of different IPs also*
thanks for the help.

Try receiving in from the same IP but sending to localhost. If this works, then it's your router that is the problem as it doesn't support multicasting. If this still doesn't work then it's the IP address. try something in the 233.x.x.x - 239.x.x.x range.
I ran your code on my computer and it works fine as is, and also works if I changed the send address to localhost. Sounds like this is a problem with your router and not your code.

The network 239.0.0.0/8 is designated for administrator multi-cast traffic. If all of your machines are on the same network segment, you can use an ip in this network to play around with multi-casting.
Here is the RFC defining these:
https://www.rfc-editor.org/rfc/rfc2365
As far as sending goes... Your code should look something like this:
DatagramPacket p = ...
MulticastSocket s = new MulticastSocket(LISTENPORT);
InetAddress group = InetAddress.getByName(LISTENIP);
s.joinGroup(group);
s.send(p);
s.leaveGroup(group);

Multicast usually (in a real network) depends on the router's support. From what i know in general you can't really count on it being supported properly. I would try to send packets from a different client (command line or something else) to see if the server side is binding properly or not.
On the other side if you look here: http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml it sais that the 226 address block is marked as reserved. The referenced RFC sais:
Use of IANA Reserved Addresses
Applications MUST NOT use
addressing in the IANA reserved
blocks.
That might have something to do with it also.

You shall not use same port, try different port and create one socket for receiving and second one for sending.

When this happens on my Linux boxes I check to make sure that
1) there is a route for 224.0.0.0/4 on the correct interfaces
2) the source IP address matches one of the routes for that interface
#2 is the stickiest in my lab. If my eth1 only has a route for 10.77.4.0/24 and some box is transmitting from 10.78.5.15, then linux discards it as a "martian packet".

Related

How to bind java.net.MulticastSocket to localhost

I would like to bind a MulticastSocket to the address 127.0.0.1 (Socket should only be reachable within the current host) but with the following code example i got a
java.net.SocketException: Network is unreachable: Datagram send failed exception
Is there a way to fix the problem? Here is my code
int port = 6677;
InetAddress group = InetAddress.getByName("232.0.1.10");
try(MulticastSocket s = new MulticastSocket(new InetSocketAddress(InetAddress.getByName("127.0.0.1"),port))){
String msg = "Hello";
s.joinGroup(group);
DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),group, port);
s.send(hi);
}
Multicast is a little odd when compared to traditional UDP communication. The whole point is to share data on a known "channel", simultaneously, to anyone who wants access. This sharing is "signaled" to the network by using an IP address in the range 224.0.0.1 to 239.255.255.255. If you try to bind to 127.0.0.1, you just aren't doing Multicast anymore. And if you take a minute and think about it, that makes sense - you can't share the internal interface with other computers.

Can't receive UDP Packets in Java

I'm trying to receive some UDP packets on a Java MulticastSocket.
I can see the packets arriving in wireshark and the code works for other people, but not for me.
I honestly don't know what I'm doing wrong.
I have disabled my firewall and antivirus.
I'm running Windows 10 and IntelliJ 2017.2.5.
I'm creating a MulticastSocket with a portnumber (2000 or 2001) as a parameter.
My JRE is 1.8.0_152 and I'm using the JDK supplied by JetBrains.
This is how I'm creating the MulticastSocket:
this.socket = new MulticastSocket(this.portNum);
//this.socket = new MulticastSocket();
this.socket.setReceiveBufferSize(1 << 17);
this.socket.joinGroup(InetAddress.getByName(this.ip));
And, in a while loop, I try to receive data like this:
while(!this.socket.isClosed())
{
byte[] buffer = new byte[500];
DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length);
try
{
this.socket.receive(incomingPacket);
...
Things to check are:
Make sure you bind your UDP socket to the interface you want to receive on. This is different for Windows and for Linux. For Windows: Bind to the IP address of the interface you want to receive on. On Linux bind to 0.0.0.0 to receive on all interfaces. (Receiving just on a specific interface is non-trivial on Linux.)
Make sure your this.ip is your multicast address, e.g. 224.1.2.3.
The problem has been solved, it was an unrelated concurrency issue.

DatagramSocket Broadcast Behavior (Windows vs. Linux)

Backstory:
I have a wireless device which creates it's own SSID, assigns itself an IP address using auto-ip, and begins broadcasting discovery information to 255.255.255.255. (unfortunately, it does not easily support multicast)
What I'm trying to do:
I need to be able to receive the discovery information, then send configuration information to the device. The problem is, with auto-ip, the "IP negotiation" process can take minutes on Windows, etc (during which time I can see the broadcasts and can even send broadcast information back to the device).
So I enumerate all connected network interfaces (can't directly tell which will be used to talk to the device), create a DatagramSocket for each of their addresses, then start listening. If I receive the discovery information via a particular socket, I know I can use that same socket to send data back to the device. This works on Windows.
The problem:
On Linux and OSX, the following code does not receive broadcast packets:
byte[] addr = {(byte)169, (byte)254, (byte)6, (byte)215};
DatagramSocket foo = new DatagramSocket(new InetSocketAddress(InetAddress.getByAddress(addr), PORT_NUM));
while (true)
{
byte[] buf = new byte[256];
DatagramPacket pct = new DatagramPacket(buf, buf.length);
foo.receive(pct);
System.out.println( IoBuffer.wrap(buf).getHexDump() );
}
In order to receive broadcast packets (on Linux/OSX), I need to create my DatagramSocket using:
DatagramSocket foo = new DatagramSocket(PORT_NUM);
However, when I then use this socket to send data back to the device, the packet is routed by the OS (I'm assuming) and since the interface of interest may be in the middle of auto-ip negotiation, fails.
Thoughts on the following?
How to get the "working" Windows behavior to happen on Linux/OSX
A better way to handle this process
Thanks in advance!
I do not think this is the problem with the code. Have you checked if OSX/Linux has correctly allowed those address / port number through their firewalls? I had this simple problem too in the past =P..
FYI, there is a nice technology called Zero-configuration which was built to solve this problem. It is very easy to learn so I recommend you to having a look at that as well.
Good luck.

UDP port scanning Java finds only 1 open UDP port

I have an assigment about port scanning. I am scanning UDP ports of some IP addresses in Java.In my program (assuming everything is OK) I can only find one open UDP port. In the other hands port scanning over "nmap" I get 4 open UDP ports. Can somebody tell me why I can not find more than one ports via Java code?
By the way I can find the true open port in my code.
int startPortRange=1;
int stopPortRange=1024;
InetAddress address = InetAddress.getByName("bigblackbox.cs.binghamton.edu");
int counter=0;
for(int i=startPortRange; i <=stopPortRange; i++)
{
counter++;
try{
byte [] bytes = new byte[128];
DatagramSocket ds = new DatagramSocket();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.setSoTimeout(100);
ds.connect(address, i);
ds.send(dp);
ds.isConnected();
dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
ds.close();
System.out.println("open");
System.out.println(counter);
}
catch(InterruptedIOException e){
//System.out.println("closed");
}
catch(IOException e){
//System.out.println("closed");
}
}
Output of above code is
135 open
When I make same operation in command line using nmap I get more open ports.
I could not upload an image because I am a new user.
Thank you
It is impossible to provide a concrete answer, unless you provide at least:
The source code of your program.
An example of the (incorrect) output that you are getting.
The expected output for the same scenario.
Without this information there is no way for us to tell you what is wrong. For all we know, it could even be a simple case of your program terminating prematurely after finding an open port. Or a case of the open port that was last found overwriting the entries of the previous ones before being displayed.
In any case, it might be worthwhile to investigate what is being sent and received using a network sniffer, such as Wireshark. By comparing an nmap session with a session created by your program, you might be able to spot some significant difference that would help pinpoint the issue.
EDIT:
After having a look at your code and comparing with nmap, it seems that you are mistakenly handling the case of a SocketTimeoutException as a closed port, while it could simply be the port of a server that refuses to answer to the packet that you sent.
EDIT 2:
Here's the full story:
When a port is properly closed, the server sends back an ICMP Destination Unreachable packet with the Port unreachable error code. Java interprets this error to an IOException that you correctly consider to indicate a closed port.
An open port, on the other hand may result into two different responses from the server:
The server sends back a UDP packet, which is received by your program and definitely indicates an open port. DNS servers, for example, often respond with a Format error response. nmap shows these ports are open.
The server ignores your probe packet because it is malformed w.r.t. to the provided service. This results in a network timeout and a SocketTimeoutException in your program.
Unfortunately there is no way to tell whether a network timeout is because an active server ignored a malformed probe packet or because a packet filter cut down the probe. This is why nmap displays ports that time out as open|filtered.

UDP multicast sending on wrong NIC (Java, Mac OS X)

While working on a Java application under Mac OS X (Lion, 10.7.2, Java version "1.6.0_29"), I'm running into a strange problem while trying to send multicast UDP datagrams. The packets are only being sent on one NIC, and I have no control over which one.
The following example code illustrates what I am trying to do:
public class MCast {
public static void main(String[] args) throws IOException {
InetAddress multicastAddr = InetAddress.getByName("224.0.0.1");
int port = 58680;
byte[] data = "test".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, multicastAddr, port);
MulticastSocket socket = new MulticastSocket();
socket.joinGroup(multicastAddr);
socket.setNetworkInterface(NetworkInterface.getByName("en0"));
socket.send(packet);
System.out.println("Packet sent.");
}
}
Whilst executing this code, I am using Wireshark to examine all the traffic going out on en0. No packets are sent on the port specified. However, said packets do appear on the trace for en1.
When I disable en1, the packets go out on en0 properly.
I'm at a loss here. Does anyone know what's going on?
Multicast output interface is decided by the current routing table at the time you do the group join. In most cases that means default route, hence the en0. Adding an explicit route would help, but you can just reverse the two lines in your code to be:
socket.setNetworkInterface(NetworkInterface.getByName("en0"));
socket.joinGroup(multicastAddr);
Also, you don't need to join (nor bind()) the group if you are only sending and not listening to that multicast traffic. Instead, connect() to the group address.
You can pass a an address to the constructor of MulticastSocket. You can use it to bind it to the address you want.

Categories

Resources