FT8CN/ft8cn/app/src/main/java/com/bg7yoz/ft8cn/icom/IcomUdpClient.java

227 wiersze
7.6 KiB
Java
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}