2011-03-10 28 views
3

我正在用Java編寫一個小型的UDP服務器。當服務器收到命令('GET_VIDEO')時,他讀取一個文件('video.raw'),然後將其發送給客戶端。BufferUnderflowException?這裏?

這是我的代碼:

public class ServeurBouchon { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) throws Exception { 

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

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

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

    } 

    public static class ThreadVideo extends Thread { 

     private DatagramSocket socket; 
     private DatagramPacket packet; 

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

     public void run() { 
      String cmd = new String(packet.getData(), 0, packet.getLength()); 
      System.out.println("S:CMD reçu :" + cmd); 
      if ("GET_VIDEO".equals(cmd)) { 
       read_and_send_video(this.packet.getAddress()); 
      } else if ("TIMEOUT_REQUEST".equals(cmd)) { 
       return; 
      } else { 
       System.out.println(" Exiting ..."); 
       return; 
      } 
      System.out.println("Fin ....."); 
     } 

     private void read_and_send_video(InetAddress address) { 
      System.out.println(" reading and sending video ..."); 
      File file = new File("./video/video.raw"); 
      ByteBuffer ibb = ByteBuffer.allocate(4); 
      ibb.order(ByteOrder.BIG_ENDIAN); 

      FileInputStream fis = null; 
      DatagramPacket pack; 
      byte[] buff = new byte[4]; 
      System.out.println(" Sending ..."); 
      try { 
       fis = new FileInputStream(file); 
       int size = 0; 
       while (size != -1) { 
        size = fis.read(buff, 0, buff.length); 
        System.out.println(" size = " + size); 
        ibb.put(buff);     
        System.out.println("Size : " + ibb.getInt()); 
        int length = ibb.getInt(); 
        byte[] fbuff = new byte[length];      
        fis.read(fbuff, 0, length); 

        pack = new DatagramPacket(fbuff, fbuff.length, address, 
          packet.getPort()); 
        socket.send(pack); 
       } 

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

     } 
    } 

} 

原始文件格式是一種連續的「大小+幀」。 「size」變量包含要讀取的下一幀的大小(一個int)。當我讀文件(在該行ibb.getInt())我的問題是,我得到這個異常:

Exception in thread "main" java.nio.BufferUnderflowException 
at java.nio.Buffer.nextGetIndex(Buffer.java:480) 
at java.nio.HeapByteBuffer.getInt(HeapByteBuffer.java:336) 
at fr.sar.dss.bouchon.ServeurBouchon$ThreadVideo.read_and_send_video(ServeurBouchon.java:75) 
at fr.sar.dss.bouchon.ServeurBouchon$ThreadVideo.run(ServeurBouchon.java:48) 
at fr.sar.dss.bouchon.ServeurBouchon.main(ServeurBouchon.java:29) 

也許我這樣做不對,但有人可以告訴我哪裏是我的錯?

Thansk對您有所幫助;)

回答

16

這讀取整數。

System.out.println("Size : " + ibb.getInt()); 
int length = ibb.getInt(); 

使用此:

int length = ibb.getInt(); 
System.out.println("Size : " + length); 
-3

我終於找到了答案,以我的問題。每次使用ByteBuffer類和他的訪問方法(如getInt(),getShort(),getFloat(),array())時,都應該調用方法回滾來將當前緩衝區位置設置爲零。此代碼完全工作:

System.out.println("Size : " + ibb.getInt()); 
    ibb.rewind(); 
    int length = ibb.getInt(); 
    ibb.rewind(); 

THX對您有所幫助

+2

@埃裏克的回答是清潔 – andersoj 2012-07-06 13:35:47

+2

你不應該使用快退。你應該在你的代碼中知道每次你得到某個東西時你正在前進字節緩衝區的當前標記,並且只讀取一次你需要的值。 – 2013-04-30 14:37:37

+1

這個答案似乎缺少了一點。像getInt()這樣的方法不會簡單地以典型的getter方式返回一個值。相反,他們返回緩衝區當前位置的值並前進到下一個位置。重繞可能會奏效(就像你發現的那樣),但是如果在你對getInt()和rewind()的調用之間重寫前一個位置呢?如果你只是想使用多次讀取的值,爲什麼不把它保存到局部變量中。 – spaaarky21 2013-06-10 18:41:06