天天看點

Java網絡程式設計之IP位址

概念

IP位址對應在Java中的類是InetAddress類,在了解InetAddress之前先介紹幾個概念

  • 節點(node)

    連接配接到網絡的裝置叫節點

  • 主機(host)

    如果節點是計算機則叫主機

  • IP位址

    網絡中區分節點的唯一數字叫IP位址

InetAddress類

InetAddress是Ipv4位址和Ipv6位址的父類,它同時包含了hostname和IP位址

建立InetAddress對象

它沒有公共的構造函數,但是有一個靜态工廠方法,這個方法通過連接配接DNS伺服器來解析hostname。

​​

​InetAddress address = InetAddress.getByName("www.skybility.com");​

下面給出完整的例子

@Test
public void testGetByName() throws UnknownHostException {
    InetAddress address = InetAddress.getByName("www.baidu.com");
    System.out.println(address);//www.baidu.com/14.215.177.38      

也可以通過IP位址來查詢hostname:

InetAddress address = InetAddress.getByName("208.201.239.100");
System.out.println(address.getHostName());      

不過這個方法不太好使,大多數情況會傳回你傳入的IP位址。同時,這個方法比getByAddress更加便捷,因為可以傳入IP位址的字元串形式。

如果某個域名配置了多個IP位址,可以通過下面的方法得到這些IP位址:

public void testGetAllByName() throws UnknownHostException {
        try {
            InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");
            for (InetAddress address : addresses) {
                System.out.println(address);
            }
        } catch (UnknownHostException ex) {
            System.out.println(ex.getMessage());
        }
    }      

輸出:

www.baidu.com/14.215.177.39
www.baidu.com/14.215.177.38      

如果想知道本機位址,可通過getLocalHost來傳回

@Test
public void testGetLocalHost() throws UnknownHostException {
    InetAddress address = InetAddress.getLocalHost();
    System.out.println(address);//USERCHI-UA6LONB/192.168.5.42      

如果你知道數值形式的IP位址,那麼就可以通過調用getByAddress來建立對象,通常用來建立hostname無法解析或主機不存在的IP位址。

以下是方法簽名:

public static InetAddress getByAddress(byte[] addr) throws UnknownHostException
public static InetAddress getByAddress(String hostname, byte[] addr) throws      
public void testGetByAddress() throws UnknownHostException {
        byte[] address = {14,(byte) 215,(byte)177,39};//byte最大值127
        InetAddress lessWrong = InetAddress.getByAddress(address);
        System.out.println(lessWrong);// /14.215.177.39
        InetAddress lessWrongWithname = InetAddress.getByAddress(
                "baidu.com", address);
        System.out.println(lessWrongWithname); // baidu.com/14.215.177.39      

這個方法不保證hostname和ip位址的關聯的正确性,也就是hostname可以任意輸入。

InetAddress一旦構造好之後是無法修改的,這樣可以使它是線程安全的

Address類型

IP位址常見的類型有,127.0.0.1是本地回環位址(local loopback address);224.0.0.0~239.255.255.255是多點傳播位址(multicast address)。

Java提供了10個方法來檢測位址類型:

/**
* 傳回是否為一個通配符位址(wildcard address:0.0.0.0)
*/
public boolean isAnyLocalAddress()
//傳回是否為回環位址
public boolean isLoopbackAddress()
//傳回是否為IPV6本地鍊路位址 字首FE80::/10
public boolean isLinkLocalAddress()

public boolean isSiteLocalAddress()
/**
*傳回是否是多點傳播位址
*/
public boolean isMulticastAddress()
//傳回是否為全球多點傳播位址 以FFOE或FF1E開頭
public boolean isMCGlobal()      

用作服務端,0.0.0.0可表示本機上的任意IPV4位址

0.0.0.0和127.0.0.1的差別?

127.0.0.1 是一個環回位址。并不表示“本機”。0.0.0.0才是真正表示“本網絡中的本機”。

在實際應用中,一般我們在服務端綁定端口的時候可以選擇綁定到0.0.0.0,這樣我的服務通路方就可以通過我的多個ip位址通路我的服務。

比如我有一台伺服器,一個外放位址A,一個内網位址B,如果我綁定的端口指定了0.0.0.0,那麼通過内網位址或外網位址都可以通路我的應用。但是如果我隻綁定了内網位址,那麼通過外網位址就不能通路。 是以如果綁定0.0.0.0,也有一定安全隐患,對于隻需要内網通路的服務,可以隻綁定内網位址。

站點本地位址(SiteLocalAddress)與鍊路本地位址類似,站點本地位址可被路由器在站點或校園内傳播,但無法傳播到站點或校園之外。以FEC0:0:0:0開頭。

Inet4Address和Inet6Address

它們都繼承了InetAddress,分别表示IPv4位址和Ipv6位址。通過檢查getAddress()方法傳回的位元組數組大小可以比​

​instance of​

​ 更快的檢查InetAddress的具體類型。

NetworkInterface類

它代表了網卡,既可以是實體網卡也可以是虛拟網卡。

工廠方法

該類無法被任意的構造,可通過IP位址,名稱或枚舉得到該類的執行個體。

getByName

try {
            NetworkInterface ni = NetworkInterface.getByName("eth0");
            if (ni == null) {
                System.err.println("No such interface: eth0");
            }else{
                System.out.println(ni);//name:eth0 (VirtualBox Host-Only Ethernet Adapter)
            }

        } catch (SocketException ex) {
            System.err.println("Could not list sockets.");
        }      

getByInetAddress

.getLocalHost();
        NetworkInterface ni = NetworkInterface.getByInetAddress(address);
        System.out.println(ni);//name:eth7 (Intel(R) Ethernet Connection (2) I219-V)      

getNetworkInterfaces傳回本機所有的網卡:

.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface ni = interfaces.nextElement();
            System.out.println(ni);      
name:lo (Software Loopback Interface 1)
name:eth0 (VirtualBox Host-Only Ethernet Adapter)
name:eth1 (VMware Virtual Ethernet Adapter for VMnet8)
name:net0 (Microsoft ISATAP Adapter)
name:net1 (Teredo Tunneling Pseudo-Interface)
name:eth2 (VMware Virtual Ethernet Adapter for VMnet1)
name:net2 (WAN Miniport (L2TP))
...      

Get方法

NetworkInterface eth0 = NetworkInterface.getByName("eth0");
        Enumeration addresses = eth0.getInetAddresses();
        while (addresses.hasMoreElements()) {
            System.out.println(addresses.nextElement());