2013-04-07 73 views
0

我打算挺直了,這是作業相關的,但作業是關於使用UDP實現TCP風格的數據可靠性保證,而不是UDP套接字tom-foolery,這是我的問題是。環回地址沒有收到數據包的數據包

所以我一直在努力工作了幾個小時的Java程序,現在我開始認爲我不會找到答案。我在eclipse中使用兩個類,一個發送UDP數據報數據包,​​我已使用socketsniff進行驗證,將其綁定併發送到回送地址,並具有正確格式化的有效內容。

第二類是我有問題的地方。在接收班中,我試圖接收數據,但它永遠不會到達那裏。使用packetsniff,我發現在該套接字上甚至沒有接收調用。運行代碼時,它直接在socket.receive()調用之前的println語句,但它不會運行它。有什麼奇怪的,它會超時! 爲什麼沒有收到?

這是我的接收類的代碼。

package us.wsu.compnet.reliabletransfer; 

import java.io.*; 
import java.net.*; 

/** 
* This class implements a receiver of the Stop-And-Wait reliable transfer protocol 
*/ 
public class MyServerSocket implements Runnable { 

    private PipedOutputStream internalOutputStream; // Stream to which we write data for the upper layer 
    private PipedInputStream upperLayerStream; // Stream given to upper layer, connected to internalOutputStream 

    private DatagramSocket sock; 
    private DatagramPacket pack; 
    private byte[] buf; 
    private int seqNum; 

    /** 
    * Creates a receiver socket on a given port. 
    */ 
    public MyServerSocket(int port) throws SocketException { 
     // Open the UDP socket. 
     sock = new DatagramSocket(port); 
     System.out.println("" + sock.getInetAddress() + " " + sock.getPort() + "\n"); 
     buf = new byte[1000]; 
     pack = new DatagramPacket(buf,buf.length); 
     seqNum = 0; 

     // Create stream to the upper layer. 
     internalOutputStream = new PipedOutputStream(); 
     try {upperLayerStream = new PipedInputStream(internalOutputStream);} 
      catch (IOException e) {/* This should not happen. */} 

     // Start thread that will receive the data packets and reply with acks. 
     (new Thread(this)).start(); 
     } 

    /** 
    * Returns the InputStream associated with the socket. 
    */ 
    public InputStream getInputStream() { 
     return upperLayerStream; 
    } 

    /** 
    * Implementation of the receiver protocol. 
    */ 
    public void run() { 
     try{ 
     // Receive datagram. 
     int x = 0; 
     sock.setSoTimeout(10000); 
     while (x < 10000) 
     { 
      try{     
       System.out.println("Waiting to recieve packet"); 
       sock.receive(pack); 
       System.out.println("Packet Recieved"); 
      } 
      catch(Exception e){ 
       System.out.println("Swingandamiss!"); 
      } 
     x++; 
     } 
     // Extract sequence number and data payload. 
     MyDataPacket p; 
     pack.setData(buf,0,pack.getLength()-1); 
     p = new MyDataPacket(buf,buf.length-1); 

     // If packet is received for the first time, deliver to upper layer. 
     if (p.getSeqNum() == seqNum) 
     { 
      internalOutputStream.write(p.getData(), 0, p.getData().length); 
      seqNum = (byte) (1-seqNum); 
     }  

     // Send ack. 
     MyAckPacket ack; 
     ack = new MyAckPacket(seqNum); 
     DatagramPacket pout; 
     pout = new DatagramPacket(ack.toByteArray(),ack.toByteArray().length); 
     DatagramSocket outSock; 
     outSock = new DatagramSocket(pack.getPort(),pack.getAddress()); 
     outSock.send(pout); 
     } 
     catch (IOException e){/*Do Nothing*/} 
    } 

} 
+0

如何添加生成的輸出粘貼?另外,客戶端和服務器綁定了哪些端口號? – 2013-04-07 19:17:53

+0

此代碼的輸出是,socket.recieve函數一遍又一遍地超時。客戶端和服務器分別綁定到9876和9875。此外,在構造函數中輸出inetaddress和端口號的打印函數會輸出「null -1」 – Sidney 2013-04-07 23:36:28

+0

此代碼的輸出缺少在您嘗試發送未收到數據時所拋出的所有異常,因爲你在捕捉並忽略它們。不要這樣做。 – EJP 2013-04-08 04:06:37

回答

1

您的代碼是錯誤的。

  1. 您應該使用相同的DatagramSocket進行發送和接收。您嘗試使用源地址構建新代碼的代碼完全不正確,甚至不適用於非本地源代碼。它也泄漏插座。

  2. 您必須創建一個DatagramPacket以用目標地址和端口發送。在響應的情況下,簡單的方法是使用請求數據報,然後更改其數據,使address:port保持不變。

  3. 您絕不能忽略異常。不要欺騙他們不會發生,或者如果他們這樣做,他們可以被忽略。它們會發生,而且不容忽視。在這種情況下,如果你沒有忙於忽略它,你在發送之前會發現一個例外情況(2)。

相關問題