2011-03-09 4 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 클래스를 사용하도록 권유하지만 서버가 파일을 읽을 때 실제로 읽는 바이트 수를 모르기 때문에 사용법을 모르겠습니다. 는 모든 전송 UDP 패킷을 수신, 또는 당신은 그들이 보낸 순서대로 받게됩니다 것을 전혀 보장은 없습니다,

감사

답변

4

UDP는 신뢰할 수없는 것을 달성하기 위해 가장 좋은 방법은 무엇입니까. 각 패킷에 시퀀스 번호를 붙일 필요가 있습니다. 클라이언트에서 순서를 바꾸거나 서버에 속도를 늦추거나 (승인 메커니즘을 구현할 필요가 있습니다) 재전송을 요청할 필요가 있습니다 .

간단히 말해서 클라이언트가 대부분의 스트리밍 클라이언트와 같이 손실되거나 부적합한 패킷에 만족하지 않으면 UDP를 통해 TCP를 다시 구현하거나 TCP 만 사용해야합니다.

+1

으로 수정하십시오. 누락 된 데이터 그램뿐만 아니라 중복 된 데이터 그램도 얻을 수 있습니다. –

1

udp 서버에서 파일을 전송하는 예를 찾고 있었고 귀하의 질문을 발견했습니다. "socket.send (패킷)"

int size = 0; 
    byte[] buffer = new byte[(int) file.length()]; 
    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()); 

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

    socket.send(pack); 
} 

클라이언트에서 fos.write(rpacket.getData());fos.write(rpacket.getData(), 0, rpacket.getLength());

관련 문제