2013-07-09 18 views
1

我試圖從客戶端(普通IO)傳輸對象到服務器(NIO)。 傳輸工作正常,直到對象達到一定的大小,然後服務器將拋出一個「StreamCorruptException」,說「無效的類型代碼」。Java NIO序列化StreamCorruptException無效類型代碼

稱爲服務器上的方法如下:

private void read(SelectionKey key) throws IOException, ClassNotFoundException { 
    SocketChannel chan = (SocketChannel) key.channel(); 

    //read message object 
    ByteBuffer buf = ByteBuffer.allocate(1024); 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(buf.capacity()); 
    int length = 0; 
    int totalRead = 0; 
    int read = chan.read(buf); 
    System.out.println("read data " + read); 
    if (read >= 4) { 
     length = IoUtil.readInt(buf.array(), 0); 
     bos.write(buf.array()); 
     buf.rewind(); 
     totalRead += read; 
     LogUtil.log("length of data message is " + length); 
    } 
    while (totalRead < length) { //read until we get no more data 
     read = chan.read(buf); 
     if (read == -1) break; 
     if (read == 0) continue; 
     totalRead += read; 
     System.out.println("I've read " + read + " bytes. Total amount of bytes " + totalRead); 
     bos.write(buf.array()); 
     buf.rewind(); 
    } 

    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray(), 4, length); 
    ObjectInputStream inFromClient = new ObjectInputStream(bis); 

    Message msg = (Message) inFromClient.readObject(); 

    SocketAddress sa = chan.socket().getRemoteSocketAddress(); 
    LogUtil.log(msg.getIdentifier() + "-Message von " + sa); 


    commData.handleMessage(sa, msg); 

    } 

我預先考慮對象的大小,使NIO發揮很好。 我在這裏錯過了什麼?

回答

2

你必須考慮消息可以被分割(這是我懷疑在這裏發生的)或合併。這意味着您不能假定消息的開始和消息的結束將在讀取的開始或結束。 (它通常用於在它們之間有明顯中斷的小消息,但是這隨機失敗)

安全方法是在開始時發送一個長度並閱讀,直到您擁有該長度。如果你有更多,請保留額外的下一個閱讀。

+0

嗯,我以爲我已經在while循環 – mish

相關問題