如何在一段时间后关闭 UDP 接收套接字?

How to close UDP receiving socket after a period of time?

我这样新建一个话题

        new Thread(new Runnable() {
        @Override
        public void run() {
            DatagramSocket udpSocket = null;

            try {
                udpSocket = new DatagramSocket(null);
                udpSocket.setReuseAddress(true);
                udpSocket.setBroadcast(true);
                udpSocket.bind(new InetSocketAddress(BIND_PORT));


                InetAddress ipAddress = InetAddress.getByName(BROADCAST);
                DatagramPacket udpSendPacket = new DatagramPacket(sendMessage, sendMessage.length, ipAddress, SEND_PORT);

                // udp send
                udpSocket.send(udpSendPacket);


                // udp receive
                byte[] receiveMessage = new byte[100];
                DatagramPacket udpReceivePacket = new DatagramPacket(receiveMessage, receiveMessage.length);

                long startTime = System.currentTimeMillis();
                while ((System.currentTimeMillis()-startTime) < 5000) {
                    udpSocket.receive(udpReceivePacket);
                    Log.v(TAG, new String(receiveMessage, 0, udpReceivePacket.getLength()));

                }
                udpSocket.close();
                Log.v(TAG, "udp: close");
            } catch (Exception e) {
                Log.e(TAG, e.toString());
                e.printStackTrace();
            } finally {
                if (udpSocket != null) {
                    udpSocket.close();
                    Log.v(TAG, "udp: close");
                }
            }
        }
    }).start();

我想接收返回消息的列表,但似乎此尝试永远不会进行到最后且此套接字永远不会关闭。下次我想绑定这个端口时可能会出现一些问题。 如何确保此端口在一段时间后关闭。

如果您希望在您的时间限制内完成对 DatagramSocket.receive 的调用,您将需要调用 DatagramSocket.setSoTimeout(int),这会设置读取操作的超时时间。

您的 while 循环看起来像这样:

long startMillis = System.currentTimeMillis();
long endMillis = startMillis + 100;
long currentMillis;
try {
  while ((currentMillis = System.currentTimeMillis()) < endMillis) {
    long soTimeout = endMillis - currentMillis;
    udpSocket.setSoTimeout((int) soTimeout);
    updSocket.receive(udpReceivePacket);
    // ...
  }
} catch (SocketTimeoutException e) {
  // This means that the socket timed out without receiving data in time.
  // You can still read from the socket again (although you probably
  // want to increase the timeout again).
}

请注意,System.currentTimeMillis() 实际上并非用于测量 已用 时间,但它是挂钟时间。您也许应该使用 System.nanoTime() 来代替,它就是为此目的而设计的(显然您需要将时间除以 1e6)。