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.
Related
I've spent some time learning about UDP connections, particularly with Multicast Sockets in Java.
I was able to make a simple Multicast Socket "group chat" on my local network, but I've since been trying to expand this to work beyond my local network.
In attempts to achieve this, I port-forwarded a Class D IP address on my router in order to allow other people to access my Multicast group from outside my network.
However, when trying to connect to my "group chat" via my public IP and specified port (during the port-forwarding), I would receive the following error message...
Exception in thread "main" java.net.SocketException: Not a multicast address
at java.net.MulticastSocket.joinGroup(MulticastSocket.java:310)
...
This error makes some sense, given that my public IP isn't a class D address. But since I port-forwarded a multicast address to the specified port on my router, shouldn't this problem not occur?
Here's the relevant part of my code...
InetAddress group = InetAddress.getByName("192.___.___.___"); // my public IP
MulticastSocket socket = new MulticastSocket(1234); // the port-forwarded port
socket.joinGroup(group);
Where had I gone wrong here, and how could I get to fixing this issue?
A multicast address is between 224.0.0.0 - 239.255.255.255 with different sub-ranges within for different scenarios. More here: https://en.wikipedia.org/wiki/Multicast_address
So by attempting to join a group at 192.x.y.z, that's an invalid multicast address. That's why you get the exception thrown.
I could be mistaken, I doubt most consumer/home NAT, much less ISPs support multicast traffic. (Begs the questions - whatever happened to the MBONE - I thought that would have taken off and been the solution for everything.)
It sounds like what you need is a proxy program that intercepts multicast traffic and tunnels it to a proxy on a different network running the same code. The proxy in turn, takes the tunnelled packet and redirects back to a multicast\broadcast group.
You might have better luck with broadcast sockets instead of multicast.
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.
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);
I'm trying to receive UDP data broadcast by PlayCap to network address 192.168.103.255 port 3000 in Java, but I'm having trouble setting things up. Here's what I have:
DatagramSocket socket = new DatagramSocket();
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);
I'm getting "java.net.SocketException: already bound" from the bind call. I'm pretty inexperienced with networking, so I may be doing something way wrong here. Any help is appreciated.
Here is the stacktrace:
java.net.SocketException: already bound
at java.net.DatagramSocket.bind(Unknown Source)
at runner.main(runner.java:16)
I dont want to revive and old thread but i don't think the answer to this question is correct. I faced the same issue when i used the similar code to create a DatagramSocket.
DatagramSocket socket = new DatagramSocket();
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(InetAddress.getByName("localhost"), 5566));
This results in a SocketException
Exception in thread "main" java.net.SocketException: already bound
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at testapplication.TestApplication.main(TestApplication.java:25)
Java Result: 1
Not because there is another process occupying the same port but i have created an already BOUND datagram socket when i use the default constructor.
new DatagramSocket()
According to javadoc:
DatagramSocket()
Constructs a datagram socket and binds it to any available port on the
local host machine.
So the reason for the exception is you are trying to bind an already bound socket. To make it work you need to create an unbond socket with below constructor
DatagramSocket socket = new DatagramSocket(null);
InetSocketAddress address = new InetSocketAddress("192.168.103.255", 3000);
socket.bind(address);
Hope this helps...
Do netstat -a -o -n and from this you can find that either this port is already bind or not(even from this you can get all the bound ports).If yes , then try any other port :)
Most probably your application is running twice. Or you might be executing the same code twice. Even the same application may fail when binding twice.
Happens a lot for beginners that they didn't shut down their previous attempt (happened to me, too), and then their port is already in use. Make sure to add proper exception handling, e.g. by popping up a message "Port already in use."
Note that for listening you usually will bind a port only, without an explicit address (you might need to use "0.0.0.0" for this). Then you can receive both broadcast and unicast.
The code I use for listening to broadcasts is simply:
DatagramSocket s = new DatagramSocket();
s.bind(new InetSocketAddress(port))
Note that I'm not binding to a particular address, but only to a port.
Check the port 3000 it may be already used by another application. Try using a different port.
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".