发送int作为字节[],然后重新编程int int不工作
我想在NIO SocketChannel和阻塞IO套接字之间序列化对象。由于我无法在NIO上使用Serializable/writeObject,因此我想编写代码将对象序列化为ByteArrayOutputStream,然后发送数组长度和数组。发送int作为字节[],然后重新编程int 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()长在我的测试。是316. 我不明白为什么铸造不能正常工作。
this.getSocket().write(size);
this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray()));
如果getSocket()
结果是在非阻塞模式下的SocketChannel
,问题是在这里。您不检查write()
的结果。在非阻塞模式下,它可以写入少于ByteBuffer
中剩余的字节数;它的确可以写入零字节。
因此,youu并没有写出所有你认为正在编写的数据,所以另一端超出并读取下一个长度字作为正在写入的数据的一部分,并读取下一个数据的一部分作为下一个长度字,并得到一个错误的答案。我很惊讶,它并没有早些时候提供食物。事实上,它可能确实如此,但是你忽视IOExceptions
的可悲行为掩盖了它。不要这样做。 日志他们。
所以,你需要循环,直到所有请求的数据已经写入,如果任何write()
返回0,则需要直到它激发,增加了一个相当复杂到你的代码,你必须返回到选择环路上OP_WRITE选择同时记住有一个未完成的ByteBuffer
还有数据要写入。当你得到OP_WRITE并且写入完成时,你必须注销取消注册对OP_WRITE的兴趣,因为它仅在write()
返回零后才感兴趣。
注意:代码中没有强制转换。
现在,调用者的IOException未被屏蔽。它打印堆栈跟踪,但它永远不会抛出。 – Alessandro
write()返回0.始终。 – Alessandro
问题是write()总是返回0。发生这种情况是因为缓冲区在write()之前未被翻转。
铸造?什么铸造? – EJP