2013-07-09 3 views
1

Я пытаюсь перенести объект с клиента (обычный IO) на сервер (NIO). Передача работает нормально до тех пор, пока объект не достигнет определенного размера, тогда сервер выкинет «StreamCorruptException», указав «недопустимый код типа».Java NIO Serialization 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