1.> 转载请标明出处
本文出自[HCY的微博]
一、概述
在上篇庖丁解牛之仿《闪传》实现文件传输(上)通过WIFI API实现了两台手机所在网络的建立,那么如何让它们建立TCP连接呢?如何知道作为服务端一方的IP地址和端口号呢?方法是通过UDP多点广播(多播)服务端的Ip地址和端口号,客户端接收到这多播信息之后,连接上服务端。
二、UDP多播消息发送者
ipv4中的多播地址范围是:224.0.0.0到239.255.255.255
/**
* UDP广播发送者
*/
class MulticastSender extends BaseThread {
private MulticastSocket multicastSocket;
private String multicastHost;
private int port;
public MulticastSender(String host, int port) throws IOException,
IllegalArgumentException {
if (TextUtils.isEmpty(host)) {
throw new IllegalArgumentException("host should not be null");
}
this.multicastHost = host;
this.port = port;
multicastSocket = new MulticastSocket();
// 添加多播地址
InetAddress groupAddr = InetAddress.getByName(host);
multicastSocket.joinGroup(groupAddr);
}
/**
* 发送多播消息内部实现
*
* @param message
* @throws IOException
*/
private void sendMessageInternal(byte[] message) throws IOException {
if (message == null) {
LogUtils.i("MulticastSender,message is null");
return;
}
DatagramPacket datagramPacket = new DatagramPacket(message,
message.length);
InetAddress groupAddr = InetAddress.getByName(multicastHost);
datagramPacket.setAddress(groupAddr);// 目标接收地址需要与多播地址相同
datagramPacket.setPort(port); // 目标端口号
multicastSocket.send(datagramPacket);
}
/**
* 发送多播消息
*
* @param message
*/
public void sendMessage(byte[] message) {
MulticastMessagePool.getInstance().addMessage(message);
}
@Override
public void run() {
while (!isExit) {
byte[] message = MulticastMessagePool.getInstance().getMessage();
if (message != null) {
try {
sendMessageInternal(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
multicastSocket.close();
}
}
如上代码实现了一个多播消息发送者,发送者每次从消息池中获取到消息后将其发送出去,如果没有消息,则发送线程等待消息的到来。
三、UDP多播消息接收者
class MulticastReceiver extends BaseThread {
private MulticastSocket multicastSocket;
private String host;
private int port;
private int recvBufSize = 1024;// 接收数据缓冲区大小
private OnUdpMulticastReceiveListener udpMulticastReceiveListener;
public MulticastReceiver(String host, int port, int recvBufSize)
throws IOException, IllegalArgumentException {
if (TextUtils.isEmpty(host)) {
throw new IllegalArgumentException("host should not be null");
}
this.host = host;
this.port = port;
this.recvBufSize = recvBufSize;
multicastSocket = new MulticastSocket(port);
InetAddress groupAddr = InetAddress.getByName(host);
multicastSocket.joinGroup(groupAddr);
}
@Override
public void run() {
try {
byte buf[] = new byte[recvBufSize];
DatagramPacket datagramPacket = null;
datagramPacket = new DatagramPacket(buf, buf.length,
InetAddress.getByName(host), port);
while (!isExit) {
multicastSocket.receive(datagramPacket);
int len = datagramPacket.getLength();
byte[] receivedData = new byte[len];
System.arraycopy(buf, 0, receivedData, 0, len);
onRecieveMessage(receivedData);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
multicastSocket.close();
}
}
/**
* 设置广播接收监听器
*
* @param l
*/
public void setOnUdpMulticastReceiveListener(OnUdpMulticastReceiveListener l) {
this.udpMulticastReceiveListener = l;
}
private void onRecieveMessage(byte[] message) {
if (udpMulticastReceiveListener != null) {
udpMulticastReceiveListener.onReceive(message);
}
}
}
上述代码都在TcpUdpLibrary(https://github.com/Money888/TcpUdpLibrary)中。