几个关键的类:
- 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 地址。