Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将套接字上的int作为字节[]发送,然后重铸为int不起作用_Java_Sockets_Casting_Nio - Fatal编程技术网

Java 将套接字上的int作为字节[]发送,然后重铸为int不起作用

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

我正在尝试序列化NIO SocketChannel和阻塞IO套接字之间的对象。因为我不能在NIO上使用Serializable/writeObject,所以我想编写代码将对象序列化为ByteArrayOutputStream,然后发送数组长度,后跟数组

发送方函数是

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。总是。