簡體   English   中英

Java DatagramSocket超時,但實際上已收到

[英]Java DatagramSocket time-out but in fact received

我使用WireShark測試結果很奇怪,結果表明我的代碼可以通過套接字成功發送消息。 但是,即使我從服務器收到消息,我的程序也會拋出Timeout異常。
我不知道為什么會有超時問題。

我的代碼很簡單:

static Timer timer = new Timer();
try {
    DatagramSocket c = new DatagramSocket();

    c.setBroadcast(true);

    byte[] sendData = "messageToServer".getBytes();
    try {
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), 10000);
        c.connect(InetAddress.getByName("255.255.255.255"), 10000);
        c.send(sendPacket);
    } catch(Exception ex) {
        System.out.println(ex.toString());
    }
    timer.schedule(new receiveTask(), 2000);
} catch(Exception ex) {
    System.out.println(ex.toString());
}

我使用計時器來延遲從服務器接收消息。

receiveTask類如下所示:

public class receiveTask  extends TimerTask {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            DatagramSocket c2 = new DatagramSocket();
            c2.setSoTimeout(10000);
            byte[] recvBuf = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
            String message = "";
            while (true) {
                c2.receive(receivePacket);
                System.out.println("Receive packet from Server");
                message=new String(receivePacket.getData()).trim();
                System.out.println(message);
                System.out.println("Close the connection of server socket");
            }
        } catch(Exception ex) {
            System.out.println(ex.toString());
        }
    }
}

並且在receiveTask類中引發SocketTimeOut異常。

由於服務器可以向我發送消息(在WireShark中進行了測試),因此我認為該實現不是在服務器端。 但是什么原因導致超時呢?

為什么服務器向我返回一條消息,但我的程序無法接收到該消息?

我的Java版本是7,在我的計算機上禁用防火牆沒有區別。

任何建議將被認真考慮!

編輯:雖然問題不是關於socket.close(); 我刪除了代碼。

您可以嘗試一些方法。

首先,嘗試調用timer.schedule(new receiveTask(), 2000); 較早,以便您的receiveTask准備好在發送任何消息之前接收消息。

其次,將c.close()語句移至finally子句,尤其是receiveTaskwhile循環中的那receiveTask以確保您的套接字不會過早關閉。 所以代碼看起來像

DatagramSocket c2 = null;
try{
    c2 = new DatagramSocket();
    c2.setSoTimeout(10000);
    byte[] recvBuf = new byte[1024];
    DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
    String message = "";
    while(true){            
        c2.receive(receivePacket);
        System.out.println("Receive packet from Server");
        message=new String(receivePacket.getData()).trim();
        System.out.println(message);                
        System.out.println("Close the connection of server socket");
    }
}catch(Exception ex){
    System.out.println(ex.toString());
} finally{
    if(c2 != null)
        c2.close();
}

如果所有其他方法均失敗,請嘗試c2.setSoTimeout(0); 這將導致超時設置為infinite 但是我感覺這只是掩蓋真正問題的技巧。

感謝大家的幫助! 我問我的同事,我應該采取另一種方法:打開我自己的服務器部分以接收返回的消息。

我從其他人那里聽說java可能無法正確接收返回消息(也許這就是我總是超時的原因!),因為發送部分還可以,所以只需打開一個有關偵聽包的服務器部分,我就可以從我也要服務器!

請注意,您應該使用目標服務器的相同端口,因此您也將獲得自己發送的軟件包。 只需過濾程序的發送地址即可。

服務器端和完整的概念是這樣的:

    static DatagramSocket socket2;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // Open my own server part to listen messages from broadcast returned
        listen();
        // Sending UDP broadcast in this part as question implied
    }
    public static void listen() {
        new Thread() {
            public void run() {
                try{
                    socket2 = new DatagramSocket(10000);
                    socket2.setBroadcast(true);
                    byte[] recvBuf = new byte[1024];

                    while (true) {
                        DatagramPacket packet2 = new DatagramPacket(recvBuf, recvBuf.length);
                        try{
                            socket2.receive(packet2);
                            System.out.println("Discovery packet received from: " + packet2.getAddress().getHostAddress());
                            System.out.println("Packet received; data: " + new String(packet2.getData()));
                            String message = new String(packet2.getData());
                            System.out.println("Received: "+message);

                        }catch(Exception ex){
                            System.out.println("Cannot receive package: " + ex.getMessage());
                        }
                    }
                }catch(Exception ex){
                    socket2.close();
                    System.out.println("Server side problem occured: " + ex.getMessage());
                }
            }
        }.start();
    }

盡管您可能會注意到代碼相似,但是概念不同。

我認為,發現問題要比僅找到解決問題的方法更好!

如果我的看法是錯誤的,希望有人可以糾正它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM