package com.hdl.sdk.socket.client; import android.util.Log; 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.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.util.concurrent.atomic.AtomicBoolean; /** * Created by Tong on 2021/9/15. * 组播需要android.permission.CHANGE_WIFI_MULTICAST_STATE权限 * MulticastSocket */ 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); /** * @param sendPort -1 表示随机端口 */ private UdpClient(String ip, int port, int monitorPort, int sendPort, SocketOptions socketOptions) { this.socketOptions = socketOptions; this.ip = ip; this.port = port; this.sendPort = sendPort; this.monitorPort = monitorPort; this.receiveByte = new byte[BUFFER]; } public UdpClient(String ip, int port) { this.ip = ip; this.port = port; this.receiveByte = new byte[BUFFER]; } public static SocketBoot init(String ip, int port, int monitorPort, int sendPort, SocketOptions options) { return new SocketBoot(new UdpClient(ip, port, monitorPort, sendPort, 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 { try { mSocket = SocketPool.getInstance().getUdpSocket(new InetSocketAddress(monitorPort)); mSocket.setBroadcast(true); mSocket.setReuseAddress(true); isConnect.set(true); if (receivePacket == null) { receivePacket = new DatagramPacket(receiveByte, BUFFER); } } catch (Exception e) { isConnect.set(false); throw e; } } @Override public void disconnect() { if (mSocket != null) { mSocket.close(); } isConnect.set(false); } @Override public boolean isConnect() { return isConnect.get(); } @Override public synchronized SocketOptions getOptions() { if (socketOptions == null) { socketOptions = new SocketOptions(); } return socketOptions; } @Override public void onHandleResponse() throws Exception { if (receivePacket == null || 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()))) { 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()); 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 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; } } } } }); } }