幾個關鍵的類:
- DatagramSocket
- DatagramPacket
- NetworkInterface
1、DatagramPacket類:數據報文
如果把DatagramSocket比作創建的港口碼頭,那麼DatagramPacket就是發送和接收數據的集裝箱。
1、接收構造函數
public DatagramPacket(byte[] buf,int length) //接收數據
比如,要接收數據長度爲1024的字節,構建字節緩存區byte buf[] = new byte[1024],創建DatagramPacket只需傳入buf[]和長度,實現接收長度爲length的包。
while (true) { byte buf[] = new byte[1024]; // 接收數據 DatagramPacket packet = new DatagramPacket(buf, buf.length); datagramSocket.receive(packet); String content = new String(packet.getData()).trim(); // …… }
2、發送構造函數
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
比如,要發送數據爲byte[] data,構造函數需要字節數組,數組長度,接收端地址(IP)和端口(Port),構造數據報文包用來把長度爲length 的包傳送到指定宿主的指定的端口號。
byte[] data = paramVarArgs[0].getBytes(); DatagramPacket dataPacket = new DatagramPacket(data, data.length, inetAddress, BROADCAST_PORT); try { datagramSocket.send(dataPacket); } catch (IOException e) { e.printStackTrace(); return App.getInstance().getResources().getString(R.string.send_failed); } return App.getInstance().getResources().getString(R.string.send_success);
3、主要方法
- getAddress()返回接收或發送此數據報文的機器的 IP 地址。
- getData()返回接收的數據或發送出的數據。
- getLength()返回發送出的或接收到的數據的長度。
- getPort()返回接收或發送該數據報文的遠程主機端口號。
2、DatagramSocket類:數據報套接字
此類表示用來發送和接收數據報包的套接字。數據報套接字是包投遞服務的發送或接收點。
1、不綁定地址及端口構造函數:DatagramSocket()創建數據報套接字。
try { datagramSocket = new DatagramSocket(); datagramSocket.setBroadcast(true); } catch (Exception e) { e.printStackTrace() ; }
用於發送報文的套接字,一般不指定特定端口及地址。
2、綁定端口構造函數:DatagramSocket(int port)創建數據報套接字並將其綁定到本地主機上的指定端口。
3、綁定地址與端口構造函數:DatagramSocket(int port, InetAddress laddr)創建數據報套接字,將其綁定到指定的本地地址。
// 保持一個套接字打開,監聽該端口上所有UDP流量(0.0.0.0表示所有未處理的流量) datagramSocket = new DatagramSocket(BROADCAST_PORT, InetAddress.getByName("0.0.0.0")); datagramSocket.setBroadcast(true);
關於0.0.0.0的意義,可參考:全零網絡IP地址0.0.0.0表示意義詳談(http://www.cnblogs.com/hnrainll/archive/2011/10/13/2210101.html)
4、主要方法
- receive(DatagramPacket p)從此套接字接收數據報包。
- void send(DatagramPacket p)從此套接字發送數據報包。
- bind(SocketAddress addr)將此 DatagramSocket 綁定到特定的地址和端口。
- void close()關閉此數據報套接字。
- void connect(InetAddress address, int port)將套接字連接到此套接字的遠程地址。
- void connect(SocketAddress addr)將此套接字連接到遠程套接字地址(IP 地址 + 端口號)。
- void disconnect()斷開套接字的連接。
- getInetAddress()返回此套接字連接的地址。
- InetAddress getLocalAddress()獲取套接字綁定的本地地址。
3、NetworkInterface類:網絡接口
NetworkInterface是JDK1.4中添加的一個獲取網絡接口的類,該網絡接口既可以是物理的網絡接口,也可以是虛擬的網絡接口,而一個網絡接口通常由一個 IP 地址來表示。
既然 NetworkInterface 用來表示一個網絡接口,那麼如果可以獲得當前機器所有的網絡接口(包括物理的和虛擬的),然後篩選出表示局域網的那個網絡接口,那就可以得到機器在局域網內的 IP 地址。
NetworkInterface常用到的方法有兩個:
- getNetworkInterfaces()用於獲取當前機器上所有的網絡接口;
- getInetAddresses()用於獲取綁定到該網卡的所有的 IP 地址。
來看下這段代碼,實現的功能是遍歷所有本地網絡接口,獲取廣播地址,並向它們發送廣播報文。
// 獲取本地所有網絡接口 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface networkInterface = interfaces.nextElement(); if (networkInterface.isLoopback() || !networkInterface.isUp()) { continue; } // getInterfaceAddresses()方法返回綁定到該網絡接口的所有 IP 的集合 for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { InetAddress broadcast = interfaceAddress.getBroadcast(); / / 不廣播迴環網絡接口 if (broadcast == null) { continue; } // 發送廣播報文 try { DatagramPacket sendPacket = new DatagramPacket(data, data.length, broadcast, BROADCAST_PORT); datagramSocket.send(sendPacket); } catch (Exception e) { e.printStackTrace(); } Log.d("發送請求", getClass().getName() + ">>> Request packet sent to: " + broadcast.getHostAddress() + "; Interface: " + networkInterface.getDisplayName()); } }
getInterfaceAddresses方法返回的是一個綁定到該網絡接口的所有 InterfaceAddress 的集合。InterfaceAddress 是 JDK1.6 之後添加的類,包含 IP 地址(InetAddress),以及該地址對應的廣播地址和掩碼長度。
以上內容部分出自使用 NetworkInterface 獲得本機在局域網內的 IP 地址。