2011-03-09 78 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());

相关问题