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.
Related
I am having an UDP Netty based server. It has a SimpleChannelUpstreamHandler pipelined where I override the messageReceived method.
I need to write back some information now and then. I could only do that by using the socket information from MessageEvent.getRemoteAddress(), and the channel from MessageEvent.getChannel(). In order to be able to reuse this information I keep in in a static map.
This turns into MessageEvent.getChannel().write("foo", MessageEvent.getRemoteAddress());
What I would have expected was to have MessageEvent.getChannel().getRemoteAddress() work, which is not the case. It always gives me null.
Am I doing something wrong ?
Is there a better way for writing back than keeping the channel and remote address in some member ?
when using a UDP (Datagram) channel as a server channel, you only bind it on a local address and no connection is made. this is why there is no remote address associated with the channel and you always get null when calling MessageEvent.getChannel().getRemoteAddress(). this behavior is expected and correct. the same single UDP "server" channel handles all incoming client requests.
when using a UDP channel as a client channel, one can create a "connection" by connecting the channel to a remote address. in this case the channel will have a configured remote address (although no actual connection is made) and calling MessageEvent.getChannel().getRemoteAddress() will return the configured remote address.
connecting a UDP channel prevents the user from using the channel to send data to remotes addresses other then the one configured on the channel. trying to do so will throw an exception. connecting a client channel is optional in UDP, a client can operate properly with a channel which is only binded on a local address as long as it saves the remote address.
I think you have two options:
saving the clients remote addresses with the client identifier and using the "server" channel to sent the data. saving the channel won't work because the same channel will used for communicating with all clients.
creating a new connected channel for each client, and saving the new channels with the client identifiers.
I believe the first option is better.
As you're probably aware UDP is a connection-less transport. A single channel can receive data from, and write data to any destination address. Therefore a UDP channel does not have an associated remote address in the way that a TCP channel does. While I think it's possible to get netty to associate a UDP channel with a specific remote address, I haven't got the details to hand and, to be honest, I think getting the address from the message event is the better option.
This leads into your second question in that, yes, you will need to keep the remote address somewhere. I've not done any UDP programming in Netty so I'm not sure if you need to map the remote address to a channel object, or whether Netty is always returning the same channel object regardless. It's worth checking this as you may only need to keep a single reference to the channel.
1) Take a look at this UDP upstream handler. To get the remote address of the sender you can use the following code SocketAddress remoteAddress = datagramPacket.sender();
2) What #johnstlr mentioned is right, it is not correct to associate a UDP channel with a single remote address. But you can use a concurrent hashmap to do lookups as shown in the above file. This game server actually uses sessions which have both TCP and UDP connections. This makes it easy to send reliable data over TCP and all the frame data over UDP.
My ServerSocket listens to LAN Connections and accepts them well, but when I try to connect to the same through my Phone - using the 3G connection - it doesn't seem to connect.
I tried using getMyIP site to get the IP and try to connect to it, it does get the right IP (checked with my router) but then no connections are accepted at all.
I tried opening the port on windows 7 and on my router altogether.
I put those lines in my Server constructor:
ss = new ServerSocket(port);
host=ss.getInetAddress().getHostAddress();
and I get the ip on host to 0.0.0.0
Thanks for your help.
- While you are at LAN, you can use the Private IP as well as Public IP ranges
- But when you are using the Internet to access the Server which is at your place, then you need to have a static Public IP address.
- You can ask for a static Public IP address from your ISP at some extra cost, there are also some site over net that some how provides a static IP on the basis of your Dynamic IP.
Private IP ranges Can't be used over the Internet.
Class A - 10.0.0.0 - 10.255.255.255
Class B - 172.16.0.0 - 172.31.255.255
Class C - 192.168.0.0 - 192.168.255.255
You need to have a public IP address. If you have a router it must pass traffic for the port you want to expose to the internet to your machine. If you have a firewall, it must allow external connections to this port.
All the changes you do are the same regardless of language you use and there is nothing you can do from Java to work around needing to do these things.
Check your firewall if it allows incoming connection. You need to make and exception there.
you need to bind explicitly the IP address on your machine which is allocated for that instance of time by your ISP.
You can get the IP address allocated to you by running ipconfig command on windows command prompt.
Use the following code to bind to a specific IP address
InetSocketAddress insa = new InetSocketAddress("22.23.23.111", 9090);
ServerSocket ss = new ServerSocket();
ss.bind(insa);
String host=ss.getInetAddress().getHostAddress();
System.out.println(host);
This prints the IP address allocated to you.
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
Here's what I'm trying to do- A server sends out "Alive message to all the PCs on the network and the PCs which are up and running, respond to the call by sending their IP.
I'm looking at a lightweight piece of coding as this will form a small bit of my application.
I've looked at Jini and other services but find that I may not need even half of their features(except for the network discovery)
Is it ok if I:
1. Use a for loop where a server opens a socket, checks(using a for loop) if all the IPs x.x.x.x are reachable by sending an "Alive" message.
2. On receiving the "alive" message at the client at the specific socket, the client replies with its IP.
Is this method OK? Do you think I could do it in a better way?
Thanks!
I had a similar problem a long time ago and I resolved it as follows:
The server broadcasts a UDP packet on the network to 255.255.255.255
All reachable clients will respond with a UDP packet that include their IP and any other information you wish to send.
The packet I personally used looks like
public class UDPDiscoveryPacket{
public final long sendingTime;
public final String clientIP;
public UDPDiscoveryPacket(long sendingTime, String clientIP){
this.sendingTime = sendingTime;
this.clientIP = clientIP;
}
}
So I'm making a simple multiplayer online applet game, and I was testing it using multicast UDP sockets instead of the typical client-server connection. This is not meant to be efficient or safe for that matter, just an experiment. Only problem is, when I try to have other people join the game from their house, it won't connect them to me, but when I use two separate computers, one that's wired in and one that's on the wifi, it works seemlessly. They can join their own game and connect to their own network, but not other peoples. Am I missing something big here? I'll post the relevant code.
InetAddress group;
DatagramPacket packet;
DatagramPacket messagePacket;
MulticastSocket socket;
socket = new MulticastSocket(4446); //random port
group = InetAddress.getByName("228.5.6.7"); //multicast address
socket.joinGroup(group);
//typical code for sending a packet
packet = new DatagramPacket(messageBuf, messageBuf.length, group, 4446);
Any ideas? I'm rather new to networking but find it a fun challenge and would like to continue learning more about it..if you have any other tips on top of helping me to solve this problem it would be appreciated.
You probably figured this out by now, but yes there is a huge problem you are missing. It will always work if you are local because your router doesn't mind distributing packets behind the private LAN. Anything outside the network will not want to work because the client will try to send a packet to the server, but the server is behind a NAT(Network address translation) and since the router didn't see the server send out a packet first, the router will just discard the client's packet and never connect. However if the server sends out a udp packet to try to connect, the router likes to switch ports so you don't know which port the packet will come out of. That's what packet forwarding is for on the router. So when the client sends a packet, it goes to a different port than expected and the router still discards it. There are solutions such as "hole punching". The easiest solution tho is to have a dedicated server outside of any NAT to handle the requests.