2011-03-10 16 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