2016-05-06 8 views
-1

NIO SocketChannelとIOソケットの間でオブジェクトをシリアル化しようとしています。私はNIO上でSerializable/writeObjectを使うことができないので、ByteArrayOutputStreamにオブジェクトを直列化し、配列の長さに続けて配列を送るコードを書くことを考えました。intをソケットとしてbyte []として送信してからintへ変換し直してください。

送信者機能が

public void writeObject(Object obj) throws IOException{ 
    ByteArrayOutputStream serializedObj = new ByteArrayOutputStream(); 
    ObjectOutputStream writer = new ObjectOutputStream(serializedObj); 
    writer.writeUnshared(obj); 
    ByteBuffer size =  ByteBuffer.allocate(4).putInt(serializedObj.toByteArray().length); 

    this.getSocket().write(size); 
    this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray())); 
} 

で、受信機は次のとおりです。

public Object readObject(){ 
    try { 
     //Leggi dimensione totale pacchetto 
     byte[] dimension = new byte[4]; 

     int byteRead = 0; 

     while(byteRead < 4) { 
      byteRead += this.getInputStream().read(dimension, byteRead, 4 - byteRead); 
     } 

     int size = ByteBuffer.wrap(dimension).getInt(); /* (*) */ 
     System.out.println(size); 

     byte[] object = new byte[size]; 

     while(size > 0){ 
      size -= this.getInputStream().read(object); 
     } 

     InputStream in = new ByteArrayInputStream(object, 0, object.length); 
     ObjectInputStream ois = new ObjectInputStream(in); 
     Object res = ois.readUnshared(); 
     ois.close(); 
     return res; 
    } catch (IOException | ClassNotFoundException e) { 
     return null; 
    } 
} 

問題は、そのサイズ(*)ですいつも私のテストでは-1393754107 serializedObj.toByteArray()の長さに等しいです。私はキャスティングが正しく動作しない理由を理解していません。

+0

キャスティング?どのようなキャスティングですか? – EJP

答えて

1
this.getSocket().write(size); 
this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray())); 

getSocket()の結果が非ブロッキングモードでSocketChannelであれば、問題はここにあります。 write()の結果を確認していません。ノンブロッキングモードでは、ByteBufferに残っているバイト数より少ないバイト数を書き込むことができます。実際にはゼロバイトを書き込むことができます。

あなたが書いていると思うすべてのデータを書いているわけではないので、もう一方の端は書かれているデータの一部として次の長さのワードをオーバランして読み込み、次のデータの一部を次の長さ言葉が間違っています。以前はバーフしていなかったのに驚いています。実際にはおそらくそうでしたが、IOExceptionsを無視するあなたの嘆かわしい習慣はそれを隠しました。それをしないでください。 ログ

したがって、要求されたすべてのデータが書き込まれるまでループする必要があり、write()がゼロを返す場合は、起動するまでOP_WRITEを選択する必要があります。これは、selectループに戻る必要があるため、未処理のデータが残っていることを覚えておいてください。ByteBuffer OP_WRITEを取得し書き込みが完了したら、 のOP_WRITEへの登録を抹消する必要があります。これは、write()がゼロを返した後にのみ重要です。

NBコードにキャスティングがありません。

+0

呼び出し元のIOExceptionがマスクされていません。スタックトレースを出力しますが、決してスローされません。 – Alessandro

+0

write()は0を返します。 – Alessandro

0

問題は常に0が返されました。これは、バッファがwrite()の前に反転されなかったために発生します。

関連する問題