Java篇:Java網路程式設計(二)網路地址及埠
2 網路地址及埠
InetAddress類表示Internet協議(IP)地址,其包含兩個由final修飾的子類Inet4Address和Inet6Address分別表示IPv4地址和IPv6地址。
目前的全球因特網所採用的協議簇是TCP/IP協議族,IP是TCP/IP協議族中網路層的協議,是TCP/IP協議族的核心協議。目前IP協議的版本號是4(簡稱IPv4),發展至今已經使用了30多年。IPv4的地址位數為32位,也就是最多有2的32次方的電腦可以聯到Internet上,近十年來由於網際網路的蓬勃發展,IP地址的發放愈趨嚴格,各項資料顯示全球IPv4地址可能在2005至2008年間全部發完。
而IPv6是下一版本地網際網路協議,它地提出最初是因為隨著網際網路地迅速發展,IPv4定義的有限地址將被耗盡,地址空間的不足必將妨礙網際網路的近一步發展。
2.1.1 InetAddress
InetAddress的構造方法並不可直接訪問,而是通過提供的6個靜態方法返回InetAddress例項。不知道是否因為現在仍是以IPv4地址為主,以下靜態方法,預設優先返回的是IPv4地址。
InetAddress對域名進行解析是使用本地機器配置或者網路命名服務(如域名系統(Domain Name System,DNS)和網路資訊服務(Network Information Service,NIS))來實現。
INETADDRESS 構造方法:通過靜態方法返回 | |
---|---|
static InetAddress[] getAllByName(String host) | 給定主機的名稱,根據系統上配置的名稱服務返回其IP地址陣列。 |
static InetAddress getByAddress(byte[] addr) | 給出原始IP地址的 InetAddress物件。 |
static InetAddress getByAddress(String host, byte[] addr) | 根據提供的主機名和IP地址建立InetAddress。 |
static InetAddress getByName(String host) |
確定主機名稱的IP地址。 |
static InetAddress getLocalHost() | 返回本地主機的地址。 |
static InetAddress getLoopbackAddress() | 返回回送地址。 |
InetAddress類提供了對IP地址進行判斷的一些方法以及返回IP地址資訊的方法。
INETADDRESS 其他方法 | |
---|---|
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
boolean isAnyLocalAddress() | 檢查萬用字元地址中的InetAddress的實用程式。 |
boolean isLinkLocalAddress() | 檢查InetAddress是否是連結本地地址的實用程式。 |
boolean isLoopbackAddress() | 檢查InetAddress是否是一個環回地址的實用程式。 |
boolean isMCGlobal() | 檢查多播地址是否具有全域性範圍的實用程式。 |
boolean isMCLinkLocal() | 檢查組播地址是否具有鏈路範圍的實用程式。 |
boolean isMCNodeLocal() | 檢查多播地址是否具有節點範圍的實用程式。 |
boolean isMCOrgLocal() | 檢查組播地址是否具有組織範圍的實用程式。 |
boolean isMCSiteLocal() | 檢查多播地址是否具有站點範圍的實用程式。 |
boolean isMulticastAddress() | 檢查InetAddress是否是IP組播地址的實用程式。 |
boolean isReachable(int timeout) | 測試該地址是否可達。 |
boolean isReachable(NetworkInterface netif, int ttl, int timeout) | 測試該地址是否可達。 |
boolean isSiteLocalAddress() | 檢查InetAddress是否是站點本地地址的實用程式。 |
byte[] getAddress() | 返回此 InetAddress物件的原始IP地址。 |
String getCanonicalHostName() | 獲取此IP地址的完全限定域名。 |
String getHostAddress() | 返回文字顯示中的IP地址字串。 |
String getHostName() | 獲取此IP地址的主機名。 |
String toString() | 將此IP地址轉換為 String 。 |
int hashCode() | 返回此IP地址的雜湊碼。 |
2.1.2 Inet4Address
Inet4Address作為InetAddress的直接子類,並沒有重寫構造方法。其支援的方法也與InetAddress相似。
INET4ADDRESS 方法 | |
---|---|
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
byte[] getAddress() | 返回此 InetAddress物件的原始IP地址。 |
以文字表示形式返回IP地址字串。 | |
int hashCode() | 返回此IP地址的雜湊碼。 |
boolean isAnyLocalAddress() | 檢查萬用字元地址中的InetAddress的實用程式。 |
boolean isLinkLocalAddress() | 檢查InetAddress是否是連結本地地址的實用程式。 |
boolean isLoopbackAddress() | 檢查InetAddress是否是一個環回地址的實用程式。 |
boolean isMCGlobal() | 檢查多播地址是否具有全域性範圍的實用程式。 |
boolean isMCLinkLocal() | 檢查組播地址是否具有鏈路範圍的實用程式。 |
boolean isMCNodeLocal() | 檢查多播地址是否具有節點範圍的實用程式。 |
boolean isMCOrgLocal() | 檢查組播地址是否具有組織範圍的實用程式。 |
boolean isMCSiteLocal() | 檢查多播地址是否具有站點範圍的實用程式。 |
boolean isMulticastAddress() | 檢查InetAddress是否是IP組播地址的實用程式。 |
boolean isSiteLocalAddress() | 檢查InetAddress是否是站點本地地址的實用程式。 |
2.1.3 Inet6Address
同樣作為作為InetAddress的直接子類,Inet6Address卻有些不同。構造Inet6Address例項的方法必須通過傳入host、addr、scope_id/NetworkInterface nif來返回。
INET6ADDRESS 構造方法:通過靜態方法返回 | |
---|---|
static Inet6Address getByAddress(String host, byte[] addr, int scope_id) | 在的確切方式建立Inet6Address, InetAddress.getByAddress(String,byte[])不同之處在於將IPv6 scope_id設定為給定數值。 |
static Inet6Address getByAddress(String host, byte[] addr, NetworkInterface nif) | 在的確切方式建立Inet6Address, InetAddress.getByAddress(String,byte[])不同之處在於將IPv6 scope_id設定為對應於在指定的地址型別的給定介面的值 addr 。 |
INET6ADDRESS 其他方法 | |
---|---|
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
byte[] getAddress() | 返回此 InetAddress物件的原始IP地址。 |
NetworkInterface getScopedInterface() | 如果此例項是使用範圍介面建立的,則返回範圍介面。 |
String getHostAddress() | 返回文字顯示中的IP地址字串。 |
int getScopeId() | 如果此例項與介面相關聯,則返回數字scopeId。 |
boolean isAnyLocalAddress() | 檢查萬用字元地址中的InetAddress的實用程式。 |
boolean isIPv4CompatibleAddress() | 檢查InetAddress是否與IPv4相容的IPv6地址的實用程式。 |
boolean isLinkLocalAddress() | 檢查InetAddress是否是連結本地地址的實用程式。 |
boolean isLoopbackAddress() | 檢查InetAddress是否是一個環回地址的實用程式。 |
boolean isMCGlobal() | 檢查多播地址是否具有全域性範圍的實用程式。 |
boolean isMCLinkLocal() | 檢查組播地址是否具有鏈路範圍的實用程式。 |
boolean isMCNodeLocal() | 檢查多播地址是否具有節點範圍的實用程式。 |
boolean isMCOrgLocal() | 檢查組播地址是否具有組織範圍的實用程式。 |
boolean isMCSiteLocal() | 檢查多播地址是否具有站點範圍的實用程式。 |
boolean isMulticastAddress() | 檢查InetAddress是否是IP組播地址的實用程式。 |
boolean isSiteLocalAddress() | 檢查InetAddress是否是站點本地地址的實用程式。 |
int hashCode() | 返回此IP地址的雜湊碼。 |
2.1.4 簡單應用
static void test1(){ try { /* ********檢視cdn中百度域名對應的IP************************* */ String hostname = "www.baidu.com"; System.out.println("域名:"+hostname); InetAddress[] addresses = InetAddress.getAllByName(hostname); int[] countIp = {0,0}; for(int i=0;i<addresses.length;i++){ //統計IPv4地址的數量 if (addresses[i] instanceof Inet4Address){ countIp[0]++; System.out.println(String.format("IPv4地址%d:%s",countIp[0],addresses[i].getHostAddress())); } // 統計IPv6地址的資料量 else if (addresses[i] instanceof Inet6Address){ countIp[1]++; System.out.println(String.format("IPv6地址%d:%s",countIp[1],addresses[i].getHostAddress())); } } System.out.println(String.format("本機IPv4地址數量:%d,IPv6地址數量:%d\n\n",countIp[0],countIp[1])); /* **********************檢視本機地址*************************************** */ // 獲取本機IP地址 InetAddress localInet = InetAddress.getLocalHost(); //獲取本機名稱 String localHostname = localInet.getHostName(); System.out.println("本機機名:"+localHostname); //根據本機名稱獲取本機全部ip(一般會包含IPv4,Ipv6的號碼) InetAddress[] localAdresses = InetAddress.getAllByName(localHostname); countIp[0]=0; countIp[1]=0; for(int i=0;i<localAdresses.length;i++){ //統計IPv4地址的數量 if (localAdresses[i] instanceof Inet4Address){ countIp[0]++; System.out.println(String.format("IPv4地址%d:%s",countIp[0],localAdresses[i].getHostAddress())); } // 統計IPv6地址的資料量 else if (localAdresses[i] instanceof Inet6Address){ countIp[1]++; System.out.println(String.format("IPv6地址%d:%s",countIp[1],localAdresses[i].getHostAddress())); } } System.out.println(String.format("本機IPv4地址數量:%d,IPv6地址數量:%d\n\n",countIp[0],countIp[1])); /* ***********************Inet6Address************************ */ /* IPv6測試的樣例好像只能找到自己本機的地址 localAdresses*/ int inet6AddressScopeId=0; String inet6AddressHostname=""; byte[] inet6AddressS={0}; for(int i=0;i<localAdresses.length;i++){ // 獲取IPv6地址 if (localAdresses[i] instanceof Inet6Address){ inet6AddressScopeId = ((Inet6Address) localAdresses[i]).getScopeId(); inet6AddressHostname = localAdresses[i].getHostName(); inet6AddressS = localAdresses[i].getAddress(); break; } } Inet6Address inet6Address = Inet6Address.getByAddress(inet6AddressHostname,inet6AddressS,inet6AddressScopeId); System.out.println(String.format("IPv6地址:%s",inet6Address.getHostAddress())); System.out.println(inet6Address.isIPv4CompatibleAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } }
2.2 網路地址+埠
2.2.1 SocketAddress
這個類代表一個沒有協議附件的Socket地址。 作為一個抽象類,它的意思是使用特定的,依賴於協議的實現進行子類化。
它提供了用於繫結,連線或返回值的套接字所使用的不可變物件。
2.2.2 InetSocketAddress
2.2.2.1 InetSocketAddress
該類實現IP套接字地址(IP地址+埠號)它也可以是一對(主機名+埠號),在這種情況下將嘗試解析主機名。 如果解決方案失敗,那麼該地址被認為是未解決的,但在某些情況下仍可以使用,例如通過代理連線。
它提供了用於繫結,連線或返回值的套接字所使用的不可變物件。
萬用字元是一個特殊的本地IP地址。 通常意味著“任何”,只能用於bind操作。
構造方法 | |
---|---|
InetSocketAddress(InetAddress addr, int port) | 從IP地址和埠號建立套接字地址。 |
InetSocketAddress(int port) | 建立一個套接字地址,其中IP地址為萬用字元地址,埠號為指定值。 |
InetSocketAddress(String hostname, int port) | 從主機名和埠號建立套接字地址。 |
MODIFIER AND TYPE | METHOD AND DESCRIPTION |
---|---|
從主機名和埠號建立未解析的套接字地址。 | |
獲得 InetAddress 。 | |
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
獲得 hostname 。 | |
如果沒有主機名(使用文字建立),則返回主機名或地址的String形式。 | |
int getPort() | 獲取埠號。 |
boolean isUnresolved() | 檢查地址是否已解析成功。 |
int hashCode() | 返回該套接字地址的雜湊碼。 |
構造此InetSocketAddress的字串表示形式。 |
2.2.2.2 程式碼應用
static void test2(){ InetSocketAddress inetSocketAddress = new InetSocketAddress(9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); try { InetAddress localInet = InetAddress.getLocalHost(); inetSocketAddress = new InetSocketAddress(localInet,9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); inetSocketAddress = InetSocketAddress.createUnresolved(localInet.getHostName(),9999); System.out.println(inetSocketAddress); System.out.println(inetSocketAddress.isUnresolved()+"\n\n"); } catch (UnknownHostException e) { e.printStackTrace(); } }
2.2.3 InterfaceAddress
此類表示網路介面地址。 簡而言之,當地址是IPv4地址時,它是一個IP地址,一個子網掩碼和一個廣播地址。 在IPv6地址的情況下,IP地址和網路字首長度。
InterfaceAddress似乎並沒有提供構造方法,一般來說應該是通過其他類來進行構建,比如NetworkInterface。
INTERFACEADDRESS包含的方法 | |
---|---|
InetAddress getAddress() | 返回此地址的 InetAddress 。 |
InetAddress getBroadcast() | InetAddress的廣播地址返回InetAddress。 |
short getNetworkPrefixLength() | 返回此地址的網路字首長度。 |
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
int hashCode() | 返回此介面地址的雜湊碼。 |
String toString() | 將此介面地址轉換為 String 。 |
2.2.4 NetworkInterface
2.2.4.1 NetworkInterface
此類表示由名稱組成的網路介面和分配給此介面的IP地址列表。 用於標識組播組所在的本地介面。 介面通常由諸如“le0”的名稱所知。
NETWORKINTERFACE包含的方法 | |
---|---|
static Enumeration<NetworkInterface> getNetworkInterfaces() | 返回本機上的所有介面。 |
static NetworkInterface getByIndex(int index) | 獲取一個網路介面給它的索引。 |
static NetworkInterface getByInetAddress(InetAddress addr) | 搜尋具有繫結到指定的Internet協議(IP)地址的網路介面的便利方法。 |
static NetworkInterface getByName(String name) | 搜尋具有指定名稱的網路介面。 |
String getDisplayName() | 獲取此網路介面的顯示名稱。 |
byte[] getHardwareAddress() | 返回介面的硬體地址(通常為MAC),如果它有一個,如果可以訪問給定當前許可權。 |
int getIndex() | 返回此網路介面的索引。 |
Enumeration<InetAddress> getInetAddresses() | 使用繫結到此網路介面的InetAddresses全部或一部分子列舉的列舉方法。 |
List<InterfaceAddress> getInterfaceAddresses() | 獲取此網路介面的 InterfaceAddresses的全部或部分的列表。 |
int getMTU() | 返回此介面的最大傳輸單元(MTU)。 |
String getName() | 獲取此網路介面的名稱。 |
NetworkInterface getParent() | 返回此介面的父NetworkInterface;如果這是一個子介面,或 null如果它是一個物理(非虛擬的)介面或沒有父。 |
Enumeration<NetworkInterface> getSubInterfaces() | 獲取連線到此網路介面的所有子介面(也稱為虛擬介面)的列舉。 |
boolean isLoopback() | 返回網路介面是否是環回介面。 |
boolean isPointToPoint() | 返回網路介面是否是點對點介面。 |
boolean isUp() | 返回網路介面是否啟動並執行。 |
boolean isVirtual() | 返回此介面是否為虛擬介面(也稱為子介面)。 |
boolean supportsMulticast() | 返回網路介面是否支援多播。 |
boolean equals(Object obj) | 將此物件與指定物件進行比較。 |
String toString() | 返回物件的字串表示形式。 |
int hashCode() | 返回物件的雜湊碼值。 |
2.2.4.2 簡單應用
-
NetworkInterface的構造方法,通過getNetworkInterfaces()返回本機全部埠,每一個NetworkInterface都會包含索引(index)、地址(Adress)、名稱(Name),獲取這些資訊就可以通過其他三個構造方法來建立對應的NetworkInterface例項。
static void test3(){ try { //返回本機上所有埠 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()){ NetworkInterface Ninterface = networkInterfaces.nextElement(); System.out.println("埠資訊:"+Ninterface); System.out.println(String.format( "介面的最大傳輸單元(MTU):%d,是否環回介面:%b,是否是點對點介面:%b,是否啟動並執行:%b,是否為虛擬介面(也稱為子介面):%b,否支援多播:%b", Ninterface.getMTU(), Ninterface.isLoopback(), Ninterface.isPointToPoint(), Ninterface.isUp(), Ninterface.isVirtual(), Ninterface.supportsMulticast() )); //獲取硬體地址 if(Ninterface.getHardwareAddress()!=null){ StringBuilder mac = new StringBuilder(); byte[] f = Ninterface.getHardwareAddress(); for(int i=0;i<f.length;i++){ String t = Integer.toHexString(0xff & f[i]); if(t.length()==1) mac.append("0"+t); else mac.append(t); if(i!=f.length-1) mac.append("-"); } System.out.println("硬體地址(如果有):"+mac); } //獲取子介面 Enumeration<NetworkInterface> subInterfaces = Ninterface.getSubInterfaces(); int subc=0; while (subInterfaces.hasMoreElements()){ NetworkInterface subInterface = subInterfaces.nextElement(); //System.out.println("埠資訊:"+subInterface); subc++; } System.out.println("子介面個數:"+subc); //getInetAddresses Enumeration<InetAddress> inetAddressEnumeration = Ninterface.getInetAddresses(); while (inetAddressEnumeration.hasMoreElements()){ System.out.println("對應的InetAddress:"+inetAddressEnumeration.nextElement()); } //List<InterfaceAddress> getInterfaceAddresses() List<InterfaceAddress> interfaceAddressList = Ninterface.getInterfaceAddresses(); for(int i=0;i<interfaceAddressList.size();i++){ System.out.println("對應的InterfaceAddress:"+interfaceAddressList.get(i)); } System.out.println("\n"); } //返回百度的埠--無法獲取資訊 String hostname = "www.baidu.com"; System.out.println("域名:"+hostname); InetAddress addresse = InetAddress.getByName(hostname); System.out.println("InetAddress:"+addresse); NetworkInterface networkInterface = NetworkInterface.getByInetAddress(addresse); System.out.println("NetworkInterface:"+networkInterface); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } }