content: package com.espressif.iot.esptouch.udp;
  
  import android.content.Context;
  import android.net.wifi.WifiManager;
  import android.util.Log;
  
  import java.io.IOException;
  import java.net.DatagramPacket;
  import java.net.DatagramSocket;
  import java.net.InetSocketAddress;
  import java.net.SocketException;
  import java.util.Arrays;
  
  public class UDPSocketServer {
      private static final String TAG = "UDPSocketServer";
      private final byte[] buffer;
      private DatagramPacket mReceivePacket;
      private DatagramSocket mServerSocket;
      private Context mContext;
      private WifiManager.MulticastLock mLock;
      private volatile boolean mIsClosed;
  
      /**
       * Constructor of UDP Socket Server
       *
       * @param port          the Socket Server port
       * @param socketTimeout the socket read timeout
       * @param context       the context of the Application
       */
      public UDPSocketServer(int port, int socketTimeout, Context context) {
          this.mContext = context;
          this.buffer = new byte[64];
          this.mReceivePacket = new DatagramPacket(buffer, 64);
          try {
              this.mServerSocket = new DatagramSocket(null);
              this.mServerSocket.setReuseAddress(true);
              this.mServerSocket.bind(new InetSocketAddress(port));
              this.mServerSocket.setSoTimeout(socketTimeout);
          } catch (IOException e) {
              Log.w(TAG, "IOException");
              e.printStackTrace();
          }
          this.mIsClosed = false;
          WifiManager manager = (WifiManager) mContext.getApplicationContext()
                  .getSystemService(Context.WIFI_SERVICE);
          mLock = manager.createMulticastLock("test wifi");
          Log.d(TAG, "mServerSocket is created, socket read timeout: "
                  + socketTimeout + ", port: " + port);
      }
  
      private synchronized void acquireLock() {
          if (mLock != null && !mLock.isHeld()) {
              mLock.acquire();
          }
      }
  
      private synchronized void releaseLock() {
          if (mLock != null && mLock.isHeld()) {
              try {
                  mLock.release();
              } catch (Throwable th) {
                  // ignoring this exception, probably wakeLock was already released
              }
          }
      }
  
      /**
       * Set the socket timeout in milliseconds
       *
       * @param timeout the timeout in milliseconds or 0 for no timeout.
       * @return true whether the timeout is set suc
       */
      public boolean setSoTimeout(int timeout) {
          try {
              this.mServerSocket.setSoTimeout(timeout);
              return true;
          } catch (SocketException e) {
              e.printStackTrace();
          }
          return false;
      }
  
      /**
       * Receive one byte from the port and convert it into String
       *
       * @return
       */
      public byte receiveOneByte() {
          Log.d(TAG, "receiveOneByte() entrance");
          try {
              acquireLock();
              mServerSocket.receive(mReceivePacket);
              Log.d(TAG, "receive: " + (mReceivePacket.getData()[0]));
              return mReceivePacket.getData()[0];
          } catch (IOException e) {
              e.printStackTrace();
          }
          return Byte.MIN_VALUE;
      }
  
      /**
       * Receive specific length bytes from the port and convert it into String
       * 21,24,-2,52,-102,-93,-60
       * 15,18,fe,34,9a,a3,c4
       *
       * @return
       */
      public byte[] receiveSpecLenBytes(int len) {
          Log.d(TAG, "receiveSpecLenBytes() entrance: len = " + len);
          try {
              acquireLock();
              mServerSocket.receive(mReceivePacket);
              byte[] recDatas = Arrays.copyOf(mReceivePacket.getData(), mReceivePacket.getLength());
              Log.d(TAG, "received len : " + recDatas.length);
              for (int i = 0; i < recDatas.length; i++) {
                  Log.w(TAG, "recDatas[" + i + "]:" + recDatas[i]);
              }
              Log.w(TAG, "receiveSpecLenBytes: " + new String(recDatas));
              if (recDatas.length != len) {
                  Log.w(TAG,
                          "received len is different from specific len, return null");
                  return null;
              }
              return recDatas;
          } catch (IOException e) {
              e.printStackTrace();
          }
          return null;
      }
  
      public void interrupt() {
          Log.i(TAG, "USPSocketServer is interrupt");
          close();
      }
  
      public synchronized void close() {
          if (!this.mIsClosed) {
              Log.w(TAG, "mServerSocket is closed");
              mServerSocket.close();
              releaseLock();
              this.mIsClosed = true;
          }
      }
  
      @Override
      protected void finalize() throws Throwable {
          close();
          super.finalize();
      }
  
  }
  