How to bind java.net.MulticastSocket to localhost - java

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.

Related

Java UDP multicast, determine which group sent packet

I'm making an application where there is a certain thread (MulticastListenerThread) which has a MulticastSocket and is listening for UDP (datagram) packets sent to the multicast group the socket is listening too.
This works. I can join a multicast group, send a message to that group and receive it through the MulticastSocket.
However, I would like to determine, from the receiver point of view, from which multicast group he received the packet. The following code gives me the address of the originator of the packet, not the multicast group:
DatagramPacket packet = new DatagramPacket(buf, buf.length);
mlcSenderSocket.receive(packet);
String src_addr = packet.getAddress().getHostAddress();
The code for sending the packet is as follows:
InetAddress address = InetAddress.getByName(dest);
packet = new DatagramPacket(payload, payload.length,
address, mlcEventPort);
LLog.out(this,"[NC] MLC packet Sent to ev port MLC " + mlcEventPort
+ " and to addr " + address);
mlcSenderSocket.send(packet);
Is it at all possible to determine which group sent the packet?
Edit:
It appears this isn't possible.
In terms of performance impact (I'm working for IoT devices), would assigning a socket per multicast group (and hence, a listener thread per group) be viable? Potentially many groups may be joined (in terms of tens or hundreds even). If it is viable, then I just need to keep the joined group address somewhere manually and refer to it as necessary.
Suggestions for other work arounds are welcome!
No group sent the packet. A socket at a specific IP address sent the packet, and the source IP address is available in the DatagramPacket. Multicast packets aren't sourced from multicast groups, they are addressed to multicast groups.
Yes it's true that you can join a MulticastSocket to multiple groups, for example:
InetAddress group;
MulticastSocket s=new MulticastSocket(12345);
NetworkInterface ni=NetworkInterface.getByName("eth1");
group=InetAddress.getByName("239.255.10.10");
s.joinGroup(new InetSocketAddress(group,12345),ni);
group=InetAddress.getByName("239.255.10.11");
s.joinGroup(new InetSocketAddress(group,12345),ni);
You then receive datagrams like this:
DatagramPacket datagram=s.receive(datagram);
Unfortunately there is no java API call in the DatagramPacket object that will allow you to determine which of the two groups was targetted by the sender, all you can get is the IP address of the network interface on which it was received (from the socket) and the sender's IP address (from the datagram).
To achieve what you want to do you're going to need to create multiple MulticastSocket objects and listen to one group per socket. You could use your own threads or NIO to listen on them all simultaneously.

Java multiple multicast sockets in same group on same host and port

I'm using multicast to implement a simple discovery service. Several instances on the application must be able to run on the same host, I therefore end up with several multicast sockets that are members of the same group on the same host.
On Linux, this works as expected. Every instance of the application on a host receives the messages sent to the multicast address.
On Windows however, only the first application to join the multicast group receives the messages sent.
Here is the code I'm using to create my multicast socket:
socket = new MulticastSocket(PORT);
InetAddress group = InetAddress.getByName(ADDRESS);
socket.joinGroup(group);
socket.setTimeToLive(TTL);
Is there some option I need to set? I've tried scouring the API but I can't find anything.
EDIT: According to this website, I need to set SO_REUSEADDR, but this can only be set before the socket binds. It seems the constructor for MulticastSocket seems to bind the socket upon creation.
you do this by creating the socket with no arguments and then call bind on that object.
socket = new MulticastSocket();
socket.setReuseAddress(true);//redundant, already set with empty constructor
SocketAddress sockAddr = new InetSocketAddress(PORT);
socket.bind(sockAddr);
InetAddress group = InetAddress.getByName(ADDRESS);
socket.joinGroup(group);
socket.setTimeToLive(TTL);

Error in multicasting a message in java

I need to multicast a message across connected clients but facing a problem. I have tried the following snippet for this link:
String msg = "Hello";
InetAddress group = InetAddress.getByName("228.5.6.7");
MulticastSocket s = new MulticastSocket(6789);
s.joinGroup(group);
DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
group, 6789);
s.send(hi);
I am getting an exception:
java.net.SocketException: Not a multicast address
I tried:
localhost
127.0.0.1
192.168.1.29(my local ip)
What could have gone wrong. Being new to this topic i am unable to debug it. Thanks for any help.
Your code works for me.
You don't need to join a group to send to it. Only to receive from it. However if you do join it, you need to specify an IP address that is a valid multicast address. Despite what it says in the code you posted, clearly your actual code doesn't use a valid multicast address.

Remotely connecting two non-local computers with sockets

This question seems like something very obvious to ask, and yet I spent more than an hour trying to find an answer.
First I host and wait for someone to connect. Then, from another instance of the application, I try to connect with a socket - for the constructor, I use InetAddress, port. The port is always right, and everything works if I use "localhost" for the address. However, if I type my IP (the one I got from Googling "what is my ip"), I get an IOException. I even sent the application to someone else, gave him my IP, and it didn't work.
The aim of the application is to connect two computers. It's in Java. Here is the relevant code.
Server:
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
Client:
InetAddress a = InetAddress.getByName(ip);
Socket s = new Socket(a, port);
I don't get past that. Obviously, the values of int port and String ip are taken from text fields.
Edit: the purpose of my application is to connect two non-local computers.
As mentionned by Greg Hewgill, if you are behind a NAT Device (Router, etc...) you will have to do some Port Forwarding.
Basically, your public IP Address that you get from using "What is my IP" from google is your public IP Address, but since you are using a router with multiple computers connected to it, there is a protocol that maps multiple computers to a single public address called NAT.
What you'll need to do is tell your router to forward the incoming packets on a certain port to a certain computer.
The way to do this is highlighted in this article http://www.wikihow.com/Port-Forward

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