2011-03-09 80 views
0

我正在用Java編寫一個小的UDP服務器。 當服務器收到命令('GET_VIDEO')時,他讀取一個文件('video.raw'),然後將其發送給客戶端。我的問題是,從服務器發送的字節數不等於在客戶端接收的字節數,我的測試失敗。這裏是服務器代碼:從UDP服務器發送文件時出現問題

public class ServerMock { 

public static void main(String[] args) throws Exception { 

    byte[] buff = new byte[64]; 
    DatagramPacket packet = new DatagramPacket(buff, buff.length); 
    DatagramSocket socket = new DatagramSocket(8080); 

    System.out.println("Server started at 8080 ..."); 

    while (true) { 
     socket.receive(packet); 
     new ServerMock.ThreadVideo(socket, packet).run(); 

    } 
} 

public static class ThreadVideo implements Runnable { 

    private DatagramPacket packet; 
    private DatagramSocket socket; 

    public ThreadVideo(DatagramSocket socket, DatagramPacket packet) { 
     this.packet = packet; 
     this.socket = socket; 
    } 

    public void run() { 
     String cmd = new String(packet.getData(), 0, packet.getLength()); 
     if (cmd.equals("GET_VIDEO")) { 
      try { 
       read_and_send_video(this.packet.getAddress()); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } else { 
      System.out.println("S:Exiting ...."); 
      System.exit(0); 
     } 
    } 


    private void read_and_send_video(InetAddress address) 
      throws IOException { 

     File file = new File("./video/video.raw"); 
     FileInputStream fis = new FileInputStream(file); 
     DatagramPacket pack; 

     int size = 0; 
     byte[] buffer = new byte[64000]; 
     ByteBuffer bb = ByteBuffer.allocate(4); 
     bb.order(ByteOrder.BIG_ENDIAN); 

     while (true) { 
      size = fis.read(buffer); 
      System.out.println("Size = " + size); 

      // Envoi du contenu du fichier 
      pack = new DatagramPacket(buffer, buffer.length, address, 
        packet.getPort()); 
      socket.send(pack); 
      if (size == -1) { 
       break; 
      } 
     } 

     String cmd = "END_VIDEO"; 
     pack = new DatagramPacket(cmd.getBytes(), cmd.getBytes().length, 
       address, packet.getPort()); 
     socket.send(pack); 

    } 

} 

}

這裏是我的客戶端代碼:

public void client(int timeout, String message) 
     throws SocketTimeoutException, SocketException { 

    try { 

     File file = new File("./video/tmp.raw"); 
     FileOutputStream fos = new FileOutputStream(file); 
     File filein = new File("./video/video.raw"); 

     InetAddress address = InetAddress.getByName(host); 
     byte[] data = message.getBytes(); 
     byte[] buffer = new byte[64000]; 

     DatagramSocket socket = new DatagramSocket(); 
     socket.setSoTimeout(timeout); 

     DatagramPacket packet = new DatagramPacket(data, data.length, 
       address, port); 
     socket.send(packet); 

     DatagramPacket rpacket = new DatagramPacket(buffer, buffer.length); 

     while (true) { 
      socket.receive(rpacket); 
      if (rpacket.getLength() <= 9) { 
       String cmd = new String(rpacket.getData(), 0, 
         rpacket.getLength()); 
       if (cmd.equals("END_VIDEO")) { 
        System.out.println("C:Fin de transmission"); 
        break; 
       } 
      } 
      fos.write(rpacket.getData()); 
     } 

     System.out.println("video.raw ->" + filein.length()); 
     System.out.println("tmp.raw -> " + file.length()); 
     Assert.assertTrue(file.length() == filein.length()); 

    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (UnknownHostException e) { 

     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

每個人都可以幫助我解決這個問題。 有些朋友建議我使用ByteBuffer類,ByteOrder類,但我不知道如何使用它們,因爲我不知道服務器讀取文件時真正讀取了多少字節。 什麼是最好的方式來實現這一

感謝

回答

4

UDP是不可靠的,有沒有保證,您將收到所有已發送的UDP數據包,或者,您將收到他們,他們發送的順序。您將需要使用序列號標記每個數據包,您將需要在客戶端重新排序它們,您需要告訴服務器何時放慢速度(或實施確認機制),您將需要能夠請求重新發送。總之,除非客戶端對丟失和亂序數據包感到滿意(因爲大多數流客戶端都是這樣),否則您將需要通過UDP重新實現TCP,或者僅使用TCP。

+1

您還可能會得到重複的數據報以及丟失的數據報。 – 2011-03-09 12:59:29

1

我正在尋找一個從udp服務器發送文件的例子,我發現你的問題。您必須修改以下行:

在服務器:

int size = 0; 
    byte[] buffer = new byte[(int) file.length()]; 
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.order(ByteOrder.BIG_ENDIAN); 

而且,你必須移動 「socket.send(包)」:

while (true) { 
size = fis.read(buffer); 
System.out.println("Size = " + size); 

// Envoi du contenu du fichier 
pack = new DatagramPacket(buffer, buffer.length, address, packet.getPort()); 

if (size == -1) { 
    break; 
} 

    socket.send(pack); 
} 

在客戶端,修改fos.write(rpacket.getData());fos.write(rpacket.getData(), 0, rpacket.getLength());

相關問題