I am working with JMDNS 3.5.4. My PC as well as other PCs are in multiple networks. I was wondering how to define the host-address (IP-address) which is broadcasted within the service.
I tried to select an address using "InetAddress.getAllByName(host)" and use this address in the create function. However, this address is simply ignored in the ServiceInfo object.
JmDNS jmdns = JmDNS.create(INETADDRESS);
// Register a service
ServiceInfo serviceInfo = ServiceInfo.create("_http._tcp.local.", "example", 1234, "path=index.html");
jmdns.registerService(serviceInfo);
Later, the clients which find the service will use its port and IP-address to call a REST-service.
It seems like the DNS cache was the problem - I deleted it.
I will evaluate my suspicion and update this post...
Related
I am using bacnet4j library to discover Remote BACnet devices. In the same network, everything is working as expected. But I could not find the BACnet controller device located in the different network.
String hostAddress="10.8.102.28";
IpNetwork network = new IpNetworkBuilder().withPort(47808).withSubnet(hostAddress, 24).build();
Transport transport = new DefaultTransport(network);
LocalDevice localDevice = new LocalDevice(Integer.decode(this.settings.getDeviceId()), transport);
localDevice.initialize();
//Finding remote device
int remoteId=1234;
RemoteDeviceFuture remoteFuture = RemoteDeviceFinder.findDevice(localDevice, remoteId);
RemoteDevice remoteDevice = null;
try {
remoteDevice = remoteFuture.get(); //remote device is null here
} catch (Exception e) {
LOGGER.error("Remote device with id " + remoteId + " does NOT exist!");
}
The above code snippet finds remote device with a given remoteId in the same network. But it can not find a device located in different network. Is there anything wrong here?
That is actually by design. The discovery process takes place using broadcast "Who-Is" messages that are not routed via IP routers. So any devices on a different IP subnet are not discovered this way. If you know the IP address of the remote device, you may be able to configure/program the IP directly as a static IP address.
However, there is something called a BBMD (BACnet Broadcast Management Device). One of these needs to be placed on each subnet, each configured with the IP address of the other BBMD. The BBMDs will intercept the BACnet related broadcasts on its subnet, send it across to the peer BBMD on the other subnet, which will retransmit the broadcast, effectively bridging the two (or more) subnets.
OR, your could configure/program your client as a "Foreign Device", have it register with a BBMD on the far subnet, which will achieve much the same.
BBMDs are fairly common. Most (all) BACnet/IP to BACnet MS/TP routers have the functionality. A lot of BACnet devices also allow the functionality to be enabled.
Hope this helps. See http://www.bacnetwiki.com for more.
UDP/IP Broadcasts - that are used as part of the 'Who-Is' (BACnet) service, generally are not routed by default and in most cases will not be allowed to be routed - e.g. security concerns been the main reason.
But if routing is in place, you could send unicast/directed traffic to the device in question.
(If I remember correctly, theoretically you should now be able to now send a Who-Is as a unicast/directed request - but even if I'm correct in saying that, it's highly likely that the majority of devices will only be listening for Who-Is services via broadcasts only.)
BBMD's are not strictly necessary - and have been considered as security concern as they can give out too much info.
It can be possible to use (effectively) bog-standard network routing instead of a BBMD - having traffic fly across a few different/target VLANs.
(Also be aware of mixing the use of a private IP(v4) address - of your choosing, and a public IP(v4) address - between the client & server/serving-device, you might encounter issues.)
Running Wildfly as Azure App Service was possible via a custom java app [https://azure.microsoft.com/en-us/documentation/articles/web-sites-java-custom-upload/]. However, app service nodes don't know the internal IP address while registering with JGroups. They always expose 127.0.0.1. In order to make JGroups cluster members communicate, we need a well known IP address of the node.
How can Wildfly determine the internal IP address of the host that it can use to register with JGroups cluster?
Per my experience, I think you can try to use Azure SDK for Java to get the internal IP address of the host from the WebSiteManagementClient.
Here is a sample code below for getting the internal IP address.
String userName = "<user-name>";
String password = "<password>";
String resourceGroupName = "<resource-group-name>";
String name = "<webapp-name>";
ServiceClientCredentials credentials = new BasicAuthenticationCredentials(userName, password);
WebSiteManagementClient webSiteManagementClient = new WebSiteManagementClientImpl(credentials);
HostingEnvironmentsOperations hostingEnvironmentsOperations = webSiteManagementClient.getHostingEnvironmentsOperations();
ServiceResponse<AddressResponse> serviceResponse = hostingEnvironmentsOperations.getHostingEnvironmentVips(resourceGroupName, name);
AddressResponse addressResponse = (AddressResponse) serviceResponse.getBody();
String internalIp = addressResponse.getInternalIpAddress();
To run the above sample, you need to add the dependent libraries into your Maven project, please see the dependencies below.
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-svc-mgmt-websites</artifactId>
<version>0.9.2</version>
</dependency>
More details for the key classes in the above sample code, please see below.
WebSiteManagementClient & WebSiteManagementClientImpl
HostingEnvironmentsOperations
AddressResponse
You could use a special keyword for the bind_addr, see [1] for details. E.g. bind_addr=match-address:192.168.1.* to try to pick an IP address on a given subnet.
[1] http://www.jgroups.org/manual/index.html#Transport
You could use Peter's code (above) to detect the available IP addresses, then set bind_addr in JGroups, e.g. like this:
InetAddress bind_addr; // detect address by using Azure's SDK
JChannel ch=new JChannel("config.xml");
TP transport=ch.getProtocolStack().getTransport();
transport.setBindAddress(bind_addr);
ch.connect("mycluster");
The important thing is that you need to set the bind address before connecting the channel.
As part of an app I'm developing, I need to be able to resolve the correct IP that corresponds with a Bonjour hostname.
For example, I'm given jack.local and need to resolve it to 192.168.1.141 which is the IP address associated with jack.
I've been combing through the JmDNS APIs and the most I can find are methods that allow resolving a Service if the type and name are known. However, I simply cannot find anything that would allow resolving a hostname.
So am I missing something? Is there really no way to resolve a hostname using JmDNS?
If you need to find out remote hostname in LAN from IP address using JmDNS you can use the following code. If you need to map from hostname to IP then you can resolve hostnames for all your subnet IPs to build a cache. If your native name resolution supports local Bonjour names you can just use InetAddress.getByName(hostname).getHostAddress().
final JmDNSImpl jmdns = new JmDNSImpl(null, null);
final HostInfo hostInfo = HostInfo.newHostInfo(InetAddress.getByName("192.168.1.78"), jmdns, null);
System.out.println("MDNS hostname (Bonjour): " + hostInfo.getName());
System.out.println("DNS hostname: " + hostInfo.getInetAddress().getHostName());
System.out.println("IP address: " + hostInfo.getInetAddress().getHostAddress());
jmdns.close();
With jmdns you listen to services. To subscribe use the functions
jmdns = JmDNS.create();
jmdns.addServiceListener(String type, ServiceListener listener);
Once jmdns finds a service the ServiceListener gets notified. The listener has three public functions:
serviceResolved(ServiceEvent event)
serviceRemoved(ServiceEvent event)
serviceAdded(ServiceEvent event)
with everyone you get the ServiceEvent. Now call event.getInfo().getHostAddresses() to get an array of all addresses of the Host.
If you want to resolve the service you have to call
jmdns.requestServiceInfo(event.getType(), event.getName(), 1);
in the serviceAdded method.
Have a look at :Quick Tutorial
I have two computers plugged in the same router of a network which I know supports IPv6. Let's call them "PC-A" and "PC-B
I want "PC-A" to figure out "PC-B"s IPv6 address and vice-versa
The first thing I do is
setSystem.setProperty("java.net.preferIPv6Addresses", "true");
If I then say
InetAddress IPAddress = InetAddress.getLocalHost();
I can get my own address which will be in IpV6 format
However, neither of the following two statements gives me "PC-B"s IPv6 address:
Inet6Address IPAddress6 = (Inet6Address)InetAddress.getByName("PC-B");
InetAddress IPAddress = InetAddress.getByName("PC-B");
I also tried to import
import com.lavantech.net.dns.SimpleDNSLookup;
import com.lavantech.net.dns.DNSLookup
The first one I am using as:
SimpleDNSLookup d = new SimpleDNSLookup();
System.out.println(d.getInet6Address("PC-B"));
and the second one as:
DNSLookup dnsLookup = new DNSLookup("PC-B", DNSLookup.QTYPE_AAAA, DNSLookup.QCLASS_IN, 3000, null);
// Get all Address Records.
ResourceRecord[] ansRecords = dnsLookup.getAAAARecords();
System.out.println(ansRecords[0]);
none of which works.
I also tried to use the following
import org.xbill.DNS.*;
int type = Type.AAAA;
Name name = Name.fromString("PC-B");
Lookup lookup = new Lookup(name, type);
lookup.run();
int result = lookup.getResult();
Record[] answers = lookup.getAnswers();
System.out.println(answers[0]);
// (where, for brevity, i am skipping the parts where I check whether result == Lookup.SUCCESSFUL
Note that if I substitute "PC-B" for, say, "ipv6.google.com" I get all the desired results!
Also note that if I just use InetAddress and Type_A wherever applicable in the above approaches, my program returns "PC-B"s IPv4 address without problem.
What am I missing?
Any help is greatly appreciated!
Your question is -unfortunately- a yet unsolved network problem dealing with host discovery on a local subnet (regardless if that subnet has a router or not).
Your desired output is clearly an IPv6 address, but it is unclear what exactly your input is.
Let's focus on PC-B. How exactly do you identify PC-B? It clear that you call it "PC-B", but that name should be configured somewhere before your PC know that that's its name. Where exactly is that configured? Is that the hostname you set on PC-B itself, or is there a domain name server (DNS) where you have given that name? If it is the name in the DNS system, you can indeed query the DNS system for the AAAA record to get the IPv6 address, but you need the fully qualified domain name (FQDN). E.g. "PC-B.yourdomain.com" rather than just "PC-B".
If you know the MAC address of PC-B, you can use the neighbour discovery protocol (NDP) to find out the IP address of PC-B.
There are network protocols that allow PC-A and PC-B to announce their names themselves, once you configured them on the local machines. Such protocols are called "service discovery" protocols, and your options here are (1) multicast DNS (mDNS) and possibly DNS service discovery (DNS-SD) on top of that; or (2) Simple Service Discovery Protocol (SSDP) in UPnP on the other hand. The advantage is that some operating systems already implement this. E.g. if PC-B is a Mac OS X host, all you need to do is query DNS for "pc-b.local" to get the answer. Unfortunately, while implementations of mDNS exist for Linux (Avahi) and Windows (Bonjour), they're not installed by default. A third alternative is to write your own host discovery protocol, and have your hosts run that protocol.
Considerations are which platforms you want to support, if installing third-party software is an option, if the discovery needs to be secure (the above options are not, look into Secure Neighbour Discovery -SEND- if this is a concern), and what input you have in the first place (the hostname "PC-B", or the type of service that runs on PC-B, e.g. _http._tcp for a webserver).
I set up a static IP and did port forwarding on my notebook, and now I have a static IP address, but it's relatively static, every time I re-start the machine, I get another address, and since I have a "static" IP I can now do Paypal IPN messaging. But how can I get this static IP from my Java program ? One way I can think of is to visit : http://portforward.com/ and on that page it tells me what my external IP is, so I can extract it with Java code, is there any other way that I can do in my Java code to get this info ?
The best solution is probably dynamic DNS. Essentially, you run a program on your computer (or router) that notifies a DNS server when your IP changes. Then, you can just tell PayPal the domain name.
There is a public service you can call with your script to retrieve your external IP address. Bear in mind they have changed the link location once. If you control your own server, you should probably write your own PHP script to simply return the address of the caller to the script.
http://www.whatismyip.com/faq/automation.asp - follow the developers link they provide
import java.net.*;
import java.io.*;
URL myExternalIP = new URL("PUT THE LINK HERE");
BufferedReader in = new BufferedReader(new InputStreamReader(
myExternalIP.openStream()));
String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
Your own server script is a simple one-liner. Create a file called whatismyip.php and here's the content.
<? echo $_SERVER['REMOTE_ADDR']?>
I see three ways of doing this:
As you discovered, querying an external server what IP you're apparently connecting from. This is simple but you require such a service to be available and, usually, that no transparent proxy messes with your results.
IGD, a sub-protocol of UPnP can give you the result very easily if your port forwarding devices supports it (many do). Google "IGD JAVA" for libraries and samples.
Register for a dynamic DNS service and then lookup your own DNS name.
You can use the NetworkInterface class:
Enumeration<NetworkInterface> ifcs = NetworkInterface.getNetworkInterfaces();
while(ifcs.hasMoreElements()){
NetworkInterface ifc = ifcs.nextElement();
System.out.println("Adresses of: "+ifc.getDisplayName());
Enumeration<InetAddress> adresses = ifc.getInetAddresses();
while(adresses.hasMoreElements()){
System.out.println(adresses.nextElement().getHostAddress());
}
}
This snippet will show you all of the interfaces and the IPs bound to them. You will need to look through the list to find the appropriate interface (see also NetworkInterface.getByName(String name)) And then look at the addresses for that interface. Once you have found the appropriate InetAdress you can use that to get the string or byte representation.