I have a client-server setup. Where client connects to the server and asks which program to execute next. Server after getting a request checks for the hostname of the other end of the socket using below chunk of code which returns "127.0.0.1"
socket.getInetAddress().getCanonicalHostName();
After getting the program name the client creates a process which also tries to connect to the server but this time the above call returns different address. "mypc.foo.com" masking the domain name here
This behavior is bugging me as I am unable to lookup the hashmap where I store all the process details grouped by the machine ip.
Is it a bug in java lookup implementation or am I missing something. Please suggest some other way to do this lookup
I beleive socket.getInetAddress() returns your own address so basically always 127.0.0.1. Try using socket.getRemoteSocketAddress() - to get the other party's ip address.
Using IP address to match distinct users is generally a bad idea though. First of all they can be in some network or behind firewall and you can get requests from multiple clients coming from the same IP address. Also you are not guaranteed that it is static or dynamic IP. And also if your application is running in some strange network setup with strange routing you might end up getting all requests from the router IP address.
The better design would be to share some token between the server and the client and use that for identification. Does it sound familiar? For example http sessions are done like that ;)
Related
I have a simple security routine that uses an MD5 hash of a concatenation of an IP address and a shared secret from client to server. (The client provides this hash to the server, and the server makes its own hash based on the client's IP and checks for equality.)
The client end may have multiple network interfaces; in development for example we have a public IP address, localhost, and a VPN network address, not to mention IPv6 addresses.
When making requests from the client to the host the client needs to concatenate the IP address of the requesting interface to the shared secret. I'm hung up on the requesting interface part. Other than making this a configuration item is there anyway to determine through the JDK which network interface will be used for resolving and transmitting to a particular host? (I already have the host name as a configuration item so that's not an issue.)
This is fundamentally a network question, not a Java question. And there is no direct way to know your own public IP address even if you only have one interface, let alone several. You could scrape your address off a site like whatismyip.com, but there is no guarantee that the route chosen by your OS to reach that site will always or ever go through the same interface as the route to the server that needs the hashed address.
I'm working on a server-client project. I hosted server on Google app engine so there is no problem with IP there, all the clients can connect to the server easily. Yet the problem occurs when I try to connect to a client, which is quite complex because I don't have static IP for the clients. Can anyone suggest me a good way for server-client coomucication in this case, without requiring that clients must have static IP address?
Thank you very much.
Well, obviously the client should register itself with the server and update it's IP when it changes.
There is, for example, a program which does exactly that and then publishes the IP with a DNS.
But you should be aware that the IPv4 address space is not that big and a lot of internet clients do not own an IP (and work thru the ISP's NAT). If you have clients that do not own an IP then you might want to stick to the usual Pull: the clients should periodically issue a request to the server to check if there are new messages for them. With a Keep-Alive connection and an efficient server implementation the price of such checks might actually be low, although that kind of communication might not work very well with the GAE pricing.
I want to find all systems that are on the same local network i.e. that have the same subnet mask.
I think I must work with InetAddress Class in Java but I don't know what should I do.
My algorithm is:
Find all available system in a local network
Check if they run on a my requested port
Keep in mind the IP of system which runs on this port
InetAddress localHost = Inet4Address.getLocalHost();
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
System.out.println(networkInterface);
networkInterface.getByInetAddress(localHost);
for (){
networkInterface.getByInetAddress(localHost)
}
I think that the networkInterface.getByInetAddress(localHost) can give me all available IP addresses in a subnet, but I don't how I can do this for all available systems, and what is the condition for the for clause.
Finding all of the possible IP addresses in an IP subnet is simple. Just write a loop that enumerates all possible byte[] representations in the subnet and constructs InetAddress instances for them.
That's the easy bit, the hard bit is solving these two problems:
how do you find all if the live IP addresses on a subnet, and
for a given IP address, how do you figure out if it is using a particular port.
The first problem can be solved in two ways:
You could use the InetAddress.isAlive() method to see if the host responds to a ping. The problem is that some hosts may be configured to not respond to pings, or the pings may be blocked by an internal firewall. This also doesn't work if the subnet is large. The problem is that you need to ping a large number of hosts, and that will take a long time and generate a lot of network traffic ... especially if there are multiple application instances doing this.
The smarter alternative is to examine your local machine's ARP cache, and extract all IP addresses that it knows about. The problem is that 1) your application may not have the access rights to access the ARP cache, 2) some IP addresses may not be in the cache, and 3) there is no way to access the ARP cache in pure Java.
The second problem depends on the nature of the service on the port:
If it is a TCP-based service, then you can attempt to connect to an IP/port using a plain socket. If the connection is accepted, then the port is in use by something. It may or may not be the service you expect, but in general the only way to tell that is to try to use the service.
If it is a UDP-based service, then there's now way in general to know if something is using the port.
I'm going to hope that you mean the following:
"I wish to discover all systems on the same local network as (the computer running my program)'s primary IP address which are listening to a certain TCP port."
With UDP, this is a slightly harder problem - you could look for bounces, but your packet may be eaten or lost (as could the reply).
Now, assuming TCP, you have three steps.
Get the IP address of the local interface you believe is the "primary" one.
Enumerate hosts on the same subnet as this address.
For each host, determine if the appropriate port is listening.
For step 1, use InetAddress.getLocalHost().
For step 2, get the subnet portion of the retrieved address, and then try every possible host within that subnet. Let's hope it's a Class C and there are only 254 hosts. There is no 100% sure way to get all the hosts without trying each one. A non-100%-certain (and more complex) way is to use ARP tables to get a router's view of the network, to send a broadcast ping to the local net, or to fall down to layer 2 and send a broadcast Ethernet packet.
For step 3, open a connection to each host on the appropriate port and then close it. If the connection times out or is denied, scratch the host. Otherwise, add it to the "listening" list. You probably want to try more than one connection at a time and set the timeout interval to something small, since most people won't be listening.
Step 4: congratulations! You've just made a very feature-poor version of nmap in Java.
I am building a Flex application which communicates with a Java server using BlazeDS.
What would be the best way to go about making the server aware of the client's hostname?
Thanks.
You can't determine the client's hostname from within Flex and it's not possible with JavaScript either. However, you can try to lookup the hostname on the server side using a reverse DNS lookup.
First, you'll need to determine the client's IP address. Take a look at "Can I get the client's IP address in an LCDS service call?" for an example on how to do it in BlazeDS.
In order to get the hostname you need to execute a reverse DNS lookup for the IP address. Please keep in mind that not every IP address has a hostname that can be determined throug reverse DNS lookups.
I want to get all the systems connected in a LAN?
Can anyone suggest me?
The Package I used in Java to achieve this was called jcifs. Here is the link to the Library .
Please note, to identify a machine on a subnet you will need to ping all the avaliable Ip addresses on the subnet. From there you can do a reverse IP Address lookup to get the machines details.
From memory from the OSI the reason why you want to ping all the machines on the network is because ICMP is still the lowest layer on the OSI Model. Though you just cannot trust just using ICMP (ping) requests to all machines on the subnet. The reason for this is most Windows Machines to prevent fishing attacks will block that protocol. So instead, you need to take a two stage detection approach. First, broadcast over the SubNet Ip address with a ICMP ping request. From the ICMP ping request after waiting 1 second, proceed to perform a SMB connection to the non responding IP addresses. You will find that most people will have either a shared printer of Microsoft Network that will respond to a request under that port.
The alternative is to use a NetBios reverse name lookup, though it still involves spamming the IP address range of the subnet.
Hope this helps.
Why do you want them, and why must they be names? Not all systems have a name.
What kind of systems are you trying to enumerate?
If you're trying to locate nearby instances of your own application, use multicast UDP to create a discovery protocol.
If you're trying to locate some server which has its own protocol for that purpose, then use its one.
If I was going to try to implement this in Java, I'd pick some unused TCP/IP port number and then try to open a socket to each IP address in the LAN's IP address range(s). You expect all the connection attempts to fail, but they should fail in different ways depending on the whether a machine is using the IP address. If an IP address is in use, you should get a "connection refused". If it is not in use, you should get a "no route to host" or "no route to network". A "connect timed out" may indicate that the host is fire-walled, or that was recently alive but is not alive at the moment.
Another approach (which I don't know is you can do from Java) is to send ARP requests for each of the IP addresses in the network address range and see what turns up in your machine's ARP cache.
And of course, you can try sending ICMP Ping messages, but they may be firewalled.
Once you have a list of live IP addresses, use DNS reverse lookup to find the corresponding DNS names. But beware that not all IP addresses are bound to DNS names.
However this is all a bit tenuous given that a lot of machines and networks use firewalls of various kinds, and these are wont to drop network messages or send misleading responses.