| | |
| | | package com.hdl.sdk.socket.client;
|
| | |
|
| | |
|
| | | import android.util.Log;
|
| | | import android.text.TextUtils;
|
| | |
|
| | | import com.hdl.sdk.common.HDLSdk;
|
| | | import com.hdl.sdk.common.utils.IpUtils;
|
| | | import com.hdl.sdk.common.utils.LogUtils;
|
| | | import com.hdl.sdk.common.utils.ThreadToolUtils;
|
| | | import com.hdl.sdk.socket.SocketBoot;
|
| | | import com.hdl.sdk.socket.SocketOptions;
|
| | | import com.hdl.sdk.socket.SocketPool;
|
| | | import com.hdl.sdk.socket.annotation.ConnectStatus;
|
| | | import com.hdl.sdk.socket.udp.UdpSocketBoot;
|
| | | import com.hdl.sdk.socket.udp.UdpSocketOptions;
|
| | | import com.hdl.sdk.socket.codec.IHandleMessage;
|
| | | import com.hdl.sdk.socket.listener.ConnectStatusListener;
|
| | |
|
| | | import java.io.IOException;
|
| | | import java.net.DatagramPacket;
|
| | | import java.net.DatagramSocket;
|
| | | import java.net.InetAddress;
|
| | | import java.net.InetSocketAddress;
|
| | | import java.util.List;
|
| | | import java.net.SocketAddress;
|
| | | import java.util.concurrent.atomic.AtomicBoolean;
|
| | |
|
| | |
|
| | | /**
|
| | | * Created by Tong on 2021/9/15.
|
| | | * 组播需要android.permission.CHANGE_WIFI_MULTICAST_STATE权限
|
| | | * MulticastSocket
|
| | | * Created by hxb on 2021/12/12.
|
| | | */
|
| | | public class UdpClient implements IClient {
|
| | |
|
| | | private static DatagramSocket mSocket;
|
| | |
|
| | | private DatagramPacket receivePacket;
|
| | |
|
| | | private final int BUFFER = 4 * 1024;
|
| | |
|
| | | private final byte[] receiveByte;
|
| | |
|
| | | private final String ip;
|
| | |
|
| | | private final int port;
|
| | |
|
| | | private int monitorPort;
|
| | | private int sendPort;
|
| | |
|
| | | private SocketOptions socketOptions;
|
| | |
|
| | | private final AtomicBoolean isConnect = new AtomicBoolean(false);
|
| | | public class UdpClient implements IUdpClient {
|
| | |
|
| | | /**
|
| | | * @param sendPort -1 表示随机端口
|
| | | * 当前socket
|
| | | */
|
| | | private UdpClient(String ip, int port, int monitorPort, int sendPort, SocketOptions socketOptions) {
|
| | | private DatagramSocket mSocket;
|
| | |
|
| | | /**
|
| | | * 接收数据包
|
| | | */
|
| | | private DatagramPacket receivePacket;
|
| | |
|
| | | /**
|
| | | * 缓冲区大小
|
| | | */
|
| | | private final int BUFFER = 2 * 1024;
|
| | |
|
| | | /**
|
| | | * 本地监听IP地址
|
| | | */
|
| | | private String ipAddress;
|
| | | /**
|
| | | * 本地监听端口
|
| | | */
|
| | | private int port;
|
| | |
|
| | | /**
|
| | | * socket配置信息
|
| | | */
|
| | | private UdpSocketOptions socketOptions;
|
| | |
|
| | | /**
|
| | | * 初始化参数
|
| | | * @param ipAddress 本地监听端口
|
| | | * @param port 本地监听端口
|
| | | * @param socketOptions
|
| | | */
|
| | | private UdpClient(String ipAddress,int port, UdpSocketOptions socketOptions) {
|
| | | this.ipAddress = ipAddress;
|
| | | this.port = port;
|
| | | this.socketOptions = socketOptions;
|
| | | this.ip = ip;
|
| | | this.port = port;
|
| | | this.sendPort = sendPort;
|
| | | this.monitorPort = monitorPort;
|
| | | this.receiveByte = new byte[BUFFER];
|
| | | byte[] receiveByte = new byte[BUFFER];
|
| | | receivePacket = new DatagramPacket(receiveByte, receiveByte.length);
|
| | | }
|
| | |
|
| | | public UdpClient(String ip, int port) {
|
| | | this.ip = ip;
|
| | | this.port = port;
|
| | | this.receiveByte = new byte[BUFFER];
|
| | | /**
|
| | | * 初始化参数
|
| | | * @param ipAddress 本地监听IP地址
|
| | | * @param port 本地监听端口
|
| | | * @param options
|
| | | * @return
|
| | | */
|
| | | public static UdpSocketBoot init(String ipAddress, int port, UdpSocketOptions options) {
|
| | | return new UdpSocketBoot(new UdpClient(ipAddress, port, options));
|
| | | }
|
| | |
|
| | | public static SocketBoot init(String ip, int port, int monitorPort, int sendPort, SocketOptions options) {
|
| | | return new SocketBoot(new UdpClient(ip, port, monitorPort, sendPort, options));
|
| | | /**
|
| | | * 初始化参数
|
| | | * @param port 本地监听端口
|
| | | * @param options
|
| | | * @return
|
| | | */
|
| | | public static UdpSocketBoot init(int port, UdpSocketOptions options) {
|
| | | return init(null, port, options);
|
| | | }
|
| | |
|
| | | public static SocketBoot init(String ip, int port, int monitorPort, SocketOptions options) {
|
| | | return init(ip, port, monitorPort, -1, options);
|
| | | }
|
| | |
|
| | | public static SocketBoot init(String ip, int port, SocketOptions options) {
|
| | | return init(ip, port, port, -1, options);
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void connect() throws Exception {
|
| | | public void bind() throws Exception {
|
| | | try {
|
| | | mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(monitorPort));
|
| | |
|
| | | //已经绑定过就不用再绑定
|
| | | if (null != mSocket) {
|
| | | return;
|
| | | }
|
| | | if (TextUtils.isEmpty(ipAddress)) {
|
| | | mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(port));
|
| | | }
|
| | | mSocket.setBroadcast(true);
|
| | | mSocket.setReuseAddress(true);
|
| | | isConnect.set(true);
|
| | | if (receivePacket == null) {
|
| | | receivePacket = new DatagramPacket(receiveByte, BUFFER);
|
| | | }
|
| | |
|
| | | } catch (Exception e) {
|
| | | isConnect.set(false);
|
| | | LogUtils.e("初始化Socket 失败:" + e.getMessage());
|
| | | throw e;
|
| | | }
|
| | |
|
| | |
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void disconnect() {
|
| | | if (mSocket != null) {
|
| | | public boolean close() {
|
| | | try {
|
| | | mSocket.close();
|
| | | } catch (Exception e) {
|
| | |
|
| | | }
|
| | | isConnect.set(false);
|
| | | mSocket = null;
|
| | | return true;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean isConnect() {
|
| | | return isConnect.get();
|
| | | }
|
| | |
|
| | | @Override
|
| | | public synchronized SocketOptions getOptions() {
|
| | | if (socketOptions == null) {
|
| | | socketOptions = new SocketOptions();
|
| | | }
|
| | | return socketOptions;
|
| | | public UdpSocketOptions getOptions() {
|
| | | return this.socketOptions;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void onHandleResponse() throws Exception {
|
| | | if (receivePacket == null || mSocket == null) {
|
| | | if (mSocket == null) {
|
| | | return;
|
| | | }
|
| | | try {
|
| | | mSocket.receive(receivePacket);
|
| | | } catch (IOException e) {
|
| | | e.printStackTrace();
|
| | | isConnect.set(false);
|
| | | }
|
| | | if (receivePacket.getLength() == 0) {
|
| | | return;
|
| | | }
|
| | | //排除自己发出去的
|
| | | try {
|
| | | if (receivePacket.getAddress().getHostAddress()
|
| | | .equals(IpUtils.getIP(HDLSdk.getInstance().getContext()))) {
|
| | | if (IpUtils.isLocalIpAddress(receivePacket.getAddress().getHostAddress()))
|
| | | return;
|
| | | }
|
| | | } catch (Exception ignored) {
|
| | |
|
| | | }
|
| | |
|
| | | IHandleMessage handleMessage = getOptions().getHandleMessage();
|
| | | if (handleMessage != null) {
|
| | | handleMessage.read(receivePacket.getData());
|
| | | }
|
| | | final String receive = new String(receivePacket.getData(), 0, receivePacket.getLength());
|
| | | try {
|
| | | LogUtils.i("接收到Udp数据包,网络地址:" + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
|
| | |
|
| | | LogUtils.d("---->", receive + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort());
|
| | |
|
| | | //重置长度
|
| | | if (receivePacket != null) {
|
| | | receivePacket.setLength(BUFFER);
|
| | | }
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void sendMsg(byte[] msg) throws Exception {
|
| | | if (msg == null) {
|
| | | msg = new byte[1];
|
| | | }
|
| | | InetAddress serverAddress = InetAddress.getByName(ip);
|
| | | final DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, serverAddress, port);
|
| | | if (sendPort < 0) {
|
| | | final DatagramSocket sendSocket = new DatagramSocket();
|
| | | sendSocket.send(sendPacket);
|
| | | sendSocket.close();
|
| | | } else if (sendPort == monitorPort) {
|
| | | mSocket.send(sendPacket);
|
| | | } else {
|
| | | final DatagramSocket sendSocket = new DatagramSocket(sendPort);
|
| | | sendSocket.send(sendPacket);
|
| | | sendSocket.close();
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void onConnectStatus(int status) {
|
| | | ThreadToolUtils.getInstance().runOnUiThread(new Runnable() {
|
| | | @Override
|
| | | public void run() {
|
| | | final List<ConnectStatusListener> list = getOptions().getConnectStatusListener();
|
| | | if (list != null && !list.isEmpty()) {
|
| | | for (ConnectStatusListener listener : list) {
|
| | | switch (status) {
|
| | | case ConnectStatus
|
| | | .CONNECTING:
|
| | | listener.onConnecting();
|
| | | break;
|
| | | case ConnectStatus
|
| | | .CONNECTED:
|
| | | listener.onConnected();
|
| | | break;
|
| | | case ConnectStatus
|
| | | .DISCONNECT:
|
| | | listener.onConnectFailed();
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | IHandleMessage handleMessage = getOptions().getHandleMessage();
|
| | | if (handleMessage != null) {
|
| | | byte[] data = new byte[receivePacket.getLength()];
|
| | | System.arraycopy(receivePacket.getData(), 0, data, 0, data.length);
|
| | | handleMessage.read(data,receivePacket.getAddress().getHostAddress());
|
| | | }
|
| | | });
|
| | |
|
| | | } catch (Exception e) {
|
| | |
|
| | | }
|
| | | }
|
| | |
|
| | |
|
| | | @Override
|
| | | public void sendMsg(String ipAddress,int port, byte[] msg) throws Exception {
|
| | | if (msg == null) {
|
| | | return;
|
| | | }
|
| | | final DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, InetAddress.getByName(ipAddress), port);
|
| | | mSocket.send(sendPacket);
|
| | | }
|
| | | }
|