package com.bg7yoz.ft8cn.icom; /** * 简单封装的udp协议处理 * @author BGY70Z * @date 2023-03-20 */ import android.util.Log; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Arrays; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class IcomUdpClient { private static final String TAG = "RadioUdpSocket"; private final int MAX_BUFFER_SIZE = 1024 *2; private DatagramSocket sendSocket; //private int remotePort; private int localPort=-1; private boolean activated = false; private OnUdpEvents onUdpEvents = null; private final ExecutorService doReceiveThreadPool = Executors.newCachedThreadPool(); private DoReceiveRunnable doReceiveRunnable=new DoReceiveRunnable(this); private final ExecutorService sendDataThreadPool = Executors.newCachedThreadPool(); private SendDataRunnable sendDataRunnable=new SendDataRunnable(this); public IcomUdpClient() {//本地端口随机 localPort=-1; } public IcomUdpClient(int localPort) {//如果localPort==-1,本地端口随机 this.localPort=localPort; } public void sendData(byte[] data, String ip,int port) throws UnknownHostException { if (!activated) return; InetAddress address = InetAddress.getByName(ip); sendDataRunnable.address=address; sendDataRunnable.data=data; sendDataRunnable.port=port; sendDataThreadPool.execute(sendDataRunnable); // new Thread(new Runnable() { // @Override // public void run() { // DatagramPacket packet = new DatagramPacket(data, data.length, address, port); // synchronized (this) { // try { // sendSocket.send(packet); // } catch (IOException e) { // e.printStackTrace(); // Log.e(TAG, "IComUdpClient: " + e.getMessage()); // if (onUdpEvents!=null){ // onUdpEvents.OnUdpSendIOException(e); // } // } // } // } // }).start(); } private static class SendDataRunnable implements Runnable{ byte[] data; int port; InetAddress address; IcomUdpClient client; public SendDataRunnable(IcomUdpClient client) { this.client = client; } @Override public void run() { DatagramPacket packet = new DatagramPacket(data, data.length, address, port); synchronized (this) { try { client.sendSocket.send(packet); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, "IComUdpClient: " + e.getMessage()); if (client.onUdpEvents!=null){ client.onUdpEvents.OnUdpSendIOException(e); } } } } } public boolean isActivated() { return activated; } public synchronized void setActivated(boolean activated) throws SocketException { this.activated = activated; if (activated) {//通过activated判断是否结束接收线程,并清空sendSocket指针 sendSocket = new DatagramSocket(); //new DatagramSocket(null);//绑定的端口号随机 sendSocket.setReuseAddress(true); if (localPort!=-1) {//绑定指定的本机端口 sendSocket.bind(new InetSocketAddress(localPort)); } //更新一下本地端口值 localPort=sendSocket.getLocalPort(); Log.e(TAG, "openUdpPort: " + sendSocket.getLocalPort()); //Log.e(TAG, "openUdpIp: " + sendSocket.getLocalAddress()); receiveData(); } else { if (sendSocket != null) { sendSocket.close(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } private void receiveData() { doReceiveThreadPool.execute(doReceiveRunnable); // new Thread(new Runnable() { // @Override // public void run() { // while (activated) { // byte[] data = new byte[MAX_BUFFER_SIZE]; // DatagramPacket packet = new DatagramPacket(data, data.length); // try { // sendSocket.receive(packet); // if (onUdpEvents != null) { // byte[] temp = Arrays.copyOf(packet.getData(), packet.getLength()); // onUdpEvents.OnReceiveData(sendSocket, packet, temp); // } // //Log.d(TAG, "receiveData:host ip: " + packet.getAddress().getHostName()); // } catch (IOException e) { // e.printStackTrace(); // Log.e(TAG, "receiveData: error:" + e.getMessage()); // } // // } // Log.e(TAG, "udpClient: is exit!"); // sendSocket.close(); // sendSocket = null; // } // }).start(); } public void setOnUdpEvents(OnUdpEvents onUdpEvents) { this.onUdpEvents = onUdpEvents; } public interface OnUdpEvents { void OnReceiveData(DatagramSocket socket, DatagramPacket packet, byte[] data); void OnUdpSendIOException(IOException e); } public int getLocalPort() { if (sendSocket != null) { return sendSocket.getLocalPort(); } else { return 0; } } public String getLocalIp() { if (sendSocket != null) { return sendSocket.getLocalAddress().toString(); } else { return "127.0.0.1"; } } public DatagramSocket getSendSocket() { return sendSocket; } public static String byteToStr(byte[] data) { StringBuilder s = new StringBuilder(); for (int i = 0; i < data.length; i++) { s.append(String.format("%02x ", data[i] & 0xff)); } return s.toString(); } private static class DoReceiveRunnable implements Runnable{ IcomUdpClient icomUdpClient; public DoReceiveRunnable(IcomUdpClient icomUdpClient) { this.icomUdpClient = icomUdpClient; } @Override public void run() { while (icomUdpClient.activated) { byte[] data = new byte[icomUdpClient.MAX_BUFFER_SIZE]; DatagramPacket packet = new DatagramPacket(data, data.length); try { icomUdpClient.sendSocket.receive(packet); if (icomUdpClient.onUdpEvents != null) { byte[] temp = Arrays.copyOf(packet.getData(), packet.getLength()); icomUdpClient.onUdpEvents.OnReceiveData(icomUdpClient.sendSocket, packet, temp); } //Log.d(TAG, "receiveData:host ip: " + packet.getAddress().getHostName()); } catch (IOException e) { e.printStackTrace(); Log.e(TAG, "receiveData: error:" + e.getMessage()); } } Log.e(TAG, "udpClient: is exit!"); icomUdpClient.sendSocket.close(); icomUdpClient.sendSocket = null; } } }