【问题标题】:set timeout for socket receive设置套接字接收超时
【发布时间】:2026-01-09 03:30:01
【问题描述】:

我想向服务器发送数据,然后等待一分钟的应答,然后关闭套接字。

怎么做?

 DatagramPacket sendpack = new ......;
 socket.send(pack);
 DatagramPacket recievepack = new .....;
 //wait 1 minute{
 socket.recieve(buf);
 //wait 1 minute}
 socket.close();

【问题讨论】:

  • 您是否需要等待一分钟或数据在套接字上可用?如果您想等待一整分钟,我会使用 sleep 或 usleep 功能。这些将在一段时间内到期,然后再继续。如果您正在等待数据,我会查看 select 函数,它允许您等待数据到达或一段时间到期,以先到者为准。
  • @Glenn 睡眠可能会浪费一分钟。如果数据在一秒钟后到达怎么办?您认为 的读取超时究竟是什么?

标签: java sockets timeout udp


【解决方案1】:

为了澄清 EJP 的评论,这就是他所说的“缺少 break”导致 SocketException。

String group = "224.0.0.0";
int port = 5000;

MulticastSocket recvSock = new MulticastSocket(port);
recvSock.joinGroup(InetAddress.getByName(group));
recvSock.setSoTimeout(1000);

while(true) {
    try {
        recvSock.receive(in);               
    } catch (SocketTimeoutException e) {
        break;  // Closing here would cause a SocketException
    }
}

// Move the close() outside the try catch bloock
recvSock.leaveGroup(InetAddress.getByName(group));
recvSock.close();

【讨论】:

    【解决方案2】:

    如果你使用DatagramSocket,或者Socket你可以使用,

    socket.setSoTimeout(1000); 
    //the value is in milliseconds
    

    有关任何详细信息,您应该查看DatagramSocket javadocSocket javadoc

    【讨论】:

    • Socket.setSoTimeout 也存在。
    【解决方案3】:

    你可以试试这个。根据您的场景需要更改套接字的超时时间!此代码将发送一条消息,然后等待接收消息,直到达到超时!

    DatagramSocket s;
    
        try {
            s = new DatagramSocket();
            byte[] buf = new byte[1000];
            DatagramPacket dp = new DatagramPacket(buf, buf.length);
            InetAddress hostAddress = InetAddress.getByName("localhost");
    
            String outString = "Say hi";        // message to send
            buf = outString.getBytes();
    
            DatagramPacket out = new DatagramPacket(buf, buf.length, hostAddress, 9999);
            s.send(out);        // send to the server
    
            s.setSoTimeout(1000);   // set the timeout in millisecounds.
    
            while(true){        // recieve data until timeout
                try {
                    s.receive(dp);
                    String rcvd = "rcvd from " + dp.getAddress() + ", " + dp.getPort() + ": "+ new String(dp.getData(), 0, dp.getLength());
                    System.out.println(rcvd);
                }
                catch (SocketTimeoutException e) {
                    // timeout exception.
                    System.out.println("Timeout reached!!! " + e);
                    s.close();
                }
            }
    
        } catch (SocketException e1) {
            // TODO Auto-generated catch block
            //e1.printStackTrace();
            System.out.println("Socket closed " + e1);
    
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    

    【讨论】:

    • 一秒对于读取超时来说太短了。由于缺少break,一旦发生超时,此代码将抛出SocketException: socket closed。并非所有SocketExceptions 都表示套接字已关闭。