2014-08-28 38 views
0

這很奇怪,我使用WireShark來測試結果,結果顯示我的代碼可以通過套接字成功發送消息。但即使我從服務器收到消息,我的程序也會拋出異常。
我不知道爲什麼會有超時問題。Java DatagramSocket超時但實際上已收到

我的代碼很簡單:

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()); 
     } 
    } 
} 

而一個SocketTimeOut異常在receiveTask類拋出。由於服務器可以向我發送消息(在WireShark中測試過),所以我不認爲服務器端是好事。但是,什麼會導致超時?

爲什麼服務器返回一條消息給我,但我無法在我的程序中收到它?

我的Java版本是7,和它沒有什麼區別禁用我的電腦上的防火牆...

任何意見,將不勝感激!

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

+0

您正在向端口10000發送消息,但您沒有收到端口10000.您在首次成功接收後關閉套接字,然後再嘗試另一個套接字。這沒有多大意義。 – EJP 2014-08-29 04:43:18

回答

0

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

我從別人那裏聽說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(); 
    } 

雖然你可能會注意到的代碼是相似的,但概念是不同的。

發現問題比找到解決問題的方法要好,我想!

如果我的意見不對,希望有人能改正它。

1

有幾件事你可以嘗試。

首先,請儘早調用timer.schedule(new receiveTask(), 2000);,這樣您的receiveTask就可以在任何發送之前接收消息。

其次,移動你的c.close()語句來finally條款,尤其是while循環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);這將導致timeout to be set to infinite。但我有一種感覺,這只是一種掩蓋真正問題的手段。

+0

感謝您的諮詢!即使嘗試其他的代碼:作爲[鏈接](http://stackoverflow.com/questions/6579350/sending-packets-to-255-255-255-255-by-java-datagramsocket-fails),它仍然沒有工作。也許這是我的電腦的問題?但我試着用C#做它,它工作正常......(但C#需要安裝.Net框架,這就是爲什麼我使用java的原因,因爲有些人使用XP並沒有.Net框架) – Shuinvy 2014-08-29 01:19:52

+0

@Shuinvy根據[這個問題](http://stackoverflow.com/q/2950715/1144203)的答案,嘗試將您的廣播地址從「255.255.255.255」更改爲「192.168.1.255」。您可能還必須使用['MulticastSocket'](http://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html)而不是'DatagramSocket'。 – 2014-08-29 02:51:55

相關問題