Java 将套接字上的int作为字节[]发送,然后重铸为int不起作用
我正在尝试序列化NIO SocketChannel和阻塞IO套接字之间的对象。因为我不能在NIO上使用Serializable/writeObject,所以我想编写代码将对象序列化为ByteArrayOutputStream,然后发送数组长度,后跟数组 发送方函数是Java 将套接字上的int作为字节[]发送,然后重铸为int不起作用,java,sockets,casting,nio,Java,Sockets,Casting,Nio,我正在尝试序列化NIO SocketChannel和阻塞IO套接字之间的对象。因为我不能在NIO上使用Serializable/writeObject,所以我想编写代码将对象序列化为ByteArrayOutputStream,然后发送数组长度,后跟数组 发送方函数是 public void writeObject(Object obj) throws IOException{ ByteArrayOutputStream serializedObj = new ByteArrayOutpu
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;
}
}
public Object readObject(){
试一试{
//Leggi Dimension Total e pacchetto
字节[]维度=新字节[4];
int byteRead=0;
while(byteRead<4){
byteRead+=this.getInputStream().read(维度,byteRead,4-byteRead);
}
int size=ByteBuffer.wrap(维度).getInt();/*(*)*/
系统输出打印项次(尺寸);
字节[]对象=新字节[大小];
而(大小>0){
size-=this.getInputStream().read(对象);
}
InputStream in=newbytearrayinputstream(object,0,object.length);
ObjectInputStream ois=新ObjectInputStream(in);
Object res=ois.readUnshared();
ois.close();
返回res;
}捕获(IOException | ClassNotFoundException e){
返回null;
}
}
问题是当序列化dobj.toByteArray()时,size(*)总是等于-1393754107。在我的测试中,长度是316。
我不明白为什么铸造不能正常工作
this.getSocket().write(size);
this.getSocket().write(ByteBuffer.wrap(serializedObj.toByteArray()));
如果getSocket()
的结果是非阻塞模式下的SocketChannel
,问题就在这里。您没有检查write()
的结果。在非阻塞模式下,它可以写入小于字节缓冲区中剩余字节数的数据;实际上,它可以写入零字节
因此,您没有写入您认为正在写入的所有数据,因此另一端溢出并读取下一个长度字作为正在写入的数据的一部分,并读取下一个数据的一部分作为下一个长度字,并得到错误的答案。我很惊讶它没早点吐出来。事实上,这可能是真的,但你忽略IOExceptions
的可悲做法掩盖了它。不要那样做。记录它们
因此,您需要循环,直到所有请求的数据都已写入,如果任何write()
返回零,则需要在OP_write上选择,直到它触发,这给您的代码增加了相当大的复杂性,因为您必须返回select循环,同时记住还有一个未完成的ByteBuffer
,还有数据需要写入。当你得到操作单元写入和写入完成时,你必须注销对操作单元写入的兴趣,因为只有在WRITE()
返回零后才有兴趣
注意:代码中没有强制转换。问题是write()始终返回0。发生这种情况是因为在write()之前缓冲区没有翻转 铸造?什么铸造?现在调用方上的IOException没有被屏蔽。它打印堆栈跟踪,但从不抛出。write()返回0。总是。