最近工作getLocalHostName返回值和linux 命令hostname返回值不太一样,就深入研究了一下jdk源码实现,请参考代码注释。
JNIEXPORT jstring JNICALL
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
char hostname[NI_MAXHOST+1];
hostname[0] = '\0';
if (JVM_GetHostName(hostname, sizeof(hostname))) {//如果获取失败,则设置默认值localhost
/* Something went wrong, maybe networking is not setup? */
strcpy(hostname, "localhost");
} else {
struct addrinfo hints, *res;
int error;
hostname[NI_MAXHOST] = '\0'; //设置默认结束符
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME; //这个参数很重要,要求返回主机规范名称,非别名
hints.ai_family = AF_INET;
error = getaddrinfo(hostname, NULL, &hints, &res); //这里hostname会重新改写
if (error == 0) {/* host is known to name service */
getnameinfo(res->ai_addr,
res->ai_addrlen,
hostname,
NI_MAXHOST,
NULL,
0,
NI_NAMEREQD);
/* if getnameinfo fails hostname is still the value
from gethostname */
freeaddrinfo(res);
}
}
return (*env)->NewStringUTF(env, hostname);
}
参照jdk的源码,我这里自己编写了一个c语言程序,如下:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#define NI_MAXHOST 1025
int main() {
char hostname[NI_MAXHOST+1] = {0};
gethostname(hostname, NI_MAXHOST);
printf("别名字name=%s\n", hostname);
struct addrinfo hints, *res;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
error = getaddrinfo(hostname, NULL, &hints, &res);
if (error == 0) {/* host is known to name service */
getnameinfo(res->ai_addr,
res->ai_addrlen,
hostname,
NI_MAXHOST,
NULL,
0,
NI_NAMEREQD);
/* if getnameinfo fails hostname is still the value
from gethostname */
freeaddrinfo(res);
}
printf("规范名字name=%s\n", hostname);
}
$ ./a.out
别名字name=test-00010-00.py
规范名字name=test-00010-00.py.mycompany.com
我这里认为规范名应该类似域名。
获取有效ip地址(除去localhost,虚拟ip等)
//指定网卡名称获取ip
public static String getIpAddrByName(String networkInterfaceName) {
try {
//get network interface by name
NetworkInterface networkInterface = NetworkInterface.getByName(networkInterfaceName);
if (networkInterface == null) {
logger.error("Interface {} is not found.", networkInterfaceName);
return "";
}
logger.info("network interface: " + networkInterface.getDisplayName());
InetAddress ipAddress = null;
//get all ip addresses band to this interface
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
ipAddress = addresses.nextElement();
if (ipAddress != null && ipAddress instanceof Inet4Address) {
return ipAddress.getHostAddress();
}
}
} catch (SocketException e) {
logger.warn("Exception ", e);
}
return "";
}
//获取所有物理网卡ip
public static List<String> getAllIpAddr() {
List<String> addressSet = new ArrayList<>();
try {
Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) en.nextElement();
Enumeration<InetAddress> enumInetAddr = ni.getInetAddresses();
while (enumInetAddr.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) enumInetAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()
&& inetAddress.isSiteLocalAddress()) {
addressSet.add(inetAddress.getHostAddress());
}
}
}
} catch (SocketException e) {
}
return addressSet;
}