当前位置: 首页 > 面试题库 >

Java-带nio的ReadObject

逄皓轩
2023-03-14
问题内容

在传统的阻塞线程服务器中,我会做这样的事情

class ServerSideThread {

    ObjectInputStream in;
    ObjectOutputStream out;
    Engine engine;

    public ServerSideThread(Socket socket, Engine engine) {
        in = new ObjectInputStream(socket.getInputStream());
        out = new ObjectOutputStream(socket.getOutputStream());
        this.engine = engine;
    }

    public void sendMessage(Message m) {
        out.writeObject(m);
    }

    public void run() {
        while(true) {
            Message m = (Message)in.readObject();
            engine.queueMessage(m,this); // give the engine a message with this as a callback
        }
    }
}

现在,可以预期该对象会很大。在我的nio循环中,我不能简单地等待对象通过,其他所有连接(工作量要小得多)都在等待我。

在告诉Nio通道已准备就绪之前,如何仅通知连接已包含整个对象?


问题答案:

您可以将对象写入ByteArrayOutputStream,以便在发送对象之前给出长度。在接收端,请先读取所需的数据量,然后再尝试对其进行解码。

但是,您可能会发现将Object * Stream与阻塞IO(而不是NIO)一起使用会更简单,更高效

像这样编辑

public static void send(SocketChannel socket,  Serializable serializable) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    for(int i=0;i<4;i++) baos.write(0);
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(serializable);
    oos.close();
    final ByteBuffer wrap = ByteBuffer.wrap(baos.toByteArray());
    wrap.putInt(0, baos.size()-4);
    socket.write(wrap);
}

private final ByteBuffer lengthByteBuffer = ByteBuffer.wrap(new byte[4]);
private ByteBuffer dataByteBuffer = null;
private boolean readLength = true;

public Serializable recv(SocketChannel socket) throws IOException, ClassNotFoundException {
    if (readLength) {
        socket.read(lengthByteBuffer);
        if (lengthByteBuffer.remaining() == 0) {
            readLength = false;
            dataByteBuffer = ByteBuffer.allocate(lengthByteBuffer.getInt(0));
            lengthByteBuffer.clear();
        }
    } else {
        socket.read(dataByteBuffer);
        if (dataByteBuffer.remaining() == 0) {
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(dataByteBuffer.array()));
            final Serializable ret = (Serializable) ois.readObject();
            // clean up
            dataByteBuffer = null;
            readLength = true;
            return ret;
        }
    }
    return null;
}


 类似资料:
  • 问题内容: 我的Web服务器使用通常的Java I/O和每个连接机制的线程。如今,随着用户的增加(长时间的轮询连接),他们开始屈服。但是,连接大部分处于空闲状态。尽管可以通过添加更多的Web服务器来解决此问题,但我一直在尝试对NIO实现进行一些研究。 我对此有好感。我已经阅读了基准测试,其中使用Linux中新的NPTL库的常规I / O 优于NIO。 通过Java I / O配置和使用最新的NPT

  • 主要内容:1 创建一个AsynchronousFileChannel,2 读取数据,3 通过Future读取数据,4 通过CompletionHandler读取数据,5 写数据,5 通过Future写入数据,6 通过CompletionHandler写入数据在Java 7中,它AsynchronousFileChannel已添加到Java NIO。这样AsynchronousFileChannel 就可以从文件中异步读取数据,或将数据异步写入文件。本教程将说明如何使用AsynchronousFi

  • 主要内容:1 打开一个DatagramChannel,2 接收数据,3 发送数据,连接到特定地址Java NIO DatagramChannel是可以发送和接收UDP数据包的通道。由于UDP是无连接的网络协议,因此默认情况下,您不能仅从DatagramChannel其他通道读取和写入内容。相反,您发送和接收数据包。 1 打开一个DatagramChannel 这是打开方式DatagramChannel: 本示例打开一个DatagramChannel,它可以在UDP端口9999上接收数据包。

  • 主要内容:1 ServerSocketChannel的介绍,2 打开一个ServerSocketChannel,3 关闭ServerSocketChannel,4 监听传入的连接,5 非阻塞模式1 ServerSocketChannel的介绍 Java NIO ServerSocketChannel是一个通道,可以侦听传入的TCP连接,就像ServerSocket在标准Java Networking中一样。该ServerSocketChannel班位于java.nio.channels包。 这是

  • 主要内容:1 打开一个SocketChannel,2 关闭一个SocketChannel,3 从SocketChannel读取,4 写入SocketChannel,5 非阻塞模式Java NIO SocketChannel是连接到TCP网络套接字的通道。它与Java NIO等效于Java Networking的Sockets。有两种SocketChannel创建方法: 您打开一个SocketChannel并连接到Internet上某个服务器。 SocketChannel可以当传入连接到达一个被创

  • 主要内容:1 打开一个文件通道,2 从文件通道读取数据,3 将数据写入文件通道,4 关闭文件通道,5 FileChannel的position()方法,6 FileChannel的size()方法,7 FileChannel的truncate()方法,8 FileChannel的force()方法Java NIO FileChannel是连接到文件的通道。使用文件通道,您可以从文件读取数据,也可以将数据写入文件。Java NIO FileChannel类是NIO的一种替代方法,它可以使用标准Ja