Netty: getting remote ip address in messageReceived - java

In my class (extends SimpleChannelHandler) I'm trying to get the ip where the message was originally sent from.
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent ev) throws Exception {
String host = ((InetSocketAddress)ctx.getChannel().getRemoteAddress()).getAddress().getHostAddress();
int port = ((InetSocketAddress)ctx.getChannel().getRemoteAddress()).getPort();
LOG.debug(String.format("host:%s port:%d", host, port));
..
This prints ip 10.0.0.1 (gateway), instead of the correct client address (10.52.45.4).
Is there any way to get the ip i'm trying to or could there be something wrong with the network configuration ?

I guess you see the gateway ip because the gateway does some kind of NAT. If so, the only chance you have is to include the source-ip address in your protocol and extract it from there.

Ip addresses starting with 10.0.0 are internal, you are probably connecting it to something on the same WiFi router. To get the 10.52.45.4 ip, you have to connect outside of your router. (don't forget to port forward)

Related

How to know ip address with java.net InetAddress or other API

I have UDP server to listen messages, and I need to bind to device IP address. Other devices send messages on the UDP server. I use next:
InetAddress address = InetAddress.getLocalHost(); // gives 127.0.1.1 (1)
address = InetAddress.getLoopbackAddress(); // 127.0.0.1 (2)
address = InetAddress.getByName("123.45.67.89"); // the same (3)
address = InetAddress.getByName("localhost"); // (4)
I run my code on different environments and see next:
On my local machine with win10 .getByName("localhost") works and .getLocalHost() not worked. Also other devices (emulators) send messages on "localhost".
On other remote PC with Win7 and some IP I'm using (1) and it works. Physical devices send messages on server IP and it process them. Also, I'm using bridge to allow devices communicate with each other, i.e. devices placed in different networks (I don't understand this configuration, it is not my).
On this remote PC but in Linux I can set address only manually, i.e. variant (3). But I need specify it automatically.
I can't get the correct server address by any method. How I can get device address? Maybe there are some another methods or API?
UPD: I'm using netty udp server with standard configuration:
#Override
public void run() {
final NioEventLoopGroup group = new NioEventLoopGroup();
try {
log.info("Started listening logs ...");
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group).channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new ChannelInitializer<NioDatagramChannel>() {
#Override
public void initChannel(final NioDatagramChannel nioDatagramChannel) {
ChannelPipeline channelPipeline = nioDatagramChannel.pipeline();
channelPipeline.addLast(encryptedPacketHandlerChain);
}
});
// Bind and start to accept incoming connections.
InetAddress address = InetAddress.getLocalHost();
System.out.println("InetAddress..getLocalHost() == " + address.getHostAddress());
address = InetAddress.getLoopbackAddress();
System.out.println("InetAddress.getLoopbackAddress == " + address.getHostAddress());
address = InetAddress.getByName(ip);
System.out.println("InetAddress.getByName " + ip + " == " + address.getHostAddress());
bootstrap.bind(address, LOG_PORT).sync().channel().closeFuture().await();
} catch (Exception e) {......
A host may have several network interfaces connected to different networks, and the bind address tells the system which interface you want to listen on. This is typically configured by the user of your application (system administrator) because the networks have different purposes (for example, data plane vs control plan: one network used by system and network admins to control the machine, another network used for production traffic)
If you don't know which interface you should listen on, you can listen on all local interfaces. You do that by binding to the special 0.0.0.0 or :: IP address.
One way you can create the 0.0.0.0 address by first creating a SocketAddress with the InetSocketAddress(int port) constructor, and then retrieving the address from it:
InetAddress anyAddress = new InetSocketAddress(LOG_PORT).getAddress();
Another way is creating the the address directly:
InetAddress anyAddress = InetAddress.getByAddress(new byte[4]);

Get global IP address from java http server

I m starting a local http server using this code:
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/intro", new MyHandler());
server.setExecutor(null);
server.start();
now I want to hit the url /intro from some other server.The problem is I don't know the ip adress to hit.Doing server.getAddress() gives 0.0.0.0:8000.I want to find the global ip address.
You have to know what is your ip (cmd and ipconfig) and get IPv4 address. But remember that is only your local IP visible in your local network, so only users in the same network can see it. In global network you are identified by your internet provider IP.
InetSocketAddress(int port)
Creates a socket address where the IP address is the wildcard address and the port number a specified value.
InetSocketAddress(InetAddress addr, int port)
Creates a socket address from an IP address and a port number.
The wildcard is a special local IP address. It usually means "any" and can only be used for bind operations.The value of this IP address is 0.0.0.0.
so use another constructor of InetSocketAddress when you can put hostname
new InetSocketAddress(String hostname, int port) calls InetAddress.getByName(hostname).
Now you shall get your local ip address when you query server.getAddress()

getting remote ip address in connectionless server

Currently I've made a connectionless server and I'd like to know a remote ip address of each udp packet.
To do so, I use
addr = ((InetSocketAddress)ctx.getChannel().getRemoteAddress()).getAddress();
in my channel handler such as
public void messageReceived(ChannelHandlerContext ctx, MessageEvent ev) throws Exception
But NullPointerException comes out. In my guess, the channel has been closed after receiving each udp packet because of connectionless channel.
How can I know it in this case?
Thanks~
I noticed the same thing, which is that the channel will not provide the remote address, but when you think about it, it's not the channel (or the DatagramSocket it wraps) that even knows about the remote address, but the Datagram itself does, which is the payload. The payload is delivered in a netty MessageEvent, and if you call MessageEvent.getRemoteAddress(), it returns what you want.
It is not clear (at least to me) what the ChannelHandlerContext class is that you are referencing.
If you use a DatagramSocket[1], you can use the receive[1] method to read UDP packets. As documented in the receive method[2], the DatagramPacket[3] will have the sender's ip address and port number.
[1] - http://docs.oracle.com/javase/6/docs/api/java/net/DatagramSocket.html
[2] - http://docs.oracle.com/javase/6/docs/api/java/net/DatagramSocket.html#receive(java.net.DatagramPacket)
[3] - http://docs.oracle.com/javase/6/docs/api/java/net/DatagramPacket.html

How to establish connections to a ServerSocket from internet?

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.

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

Categories

Resources