如何在非阻塞模式下通过SocketChannel读写序列化对象?

时间:2016-05-05 01:01:02

标签: java serialization nio objectinputstream objectoutputstream

我目前正在尝试通过NIO SocketChannel读取和编写序列化对象。此SocketChannel处于非阻塞模式。我似乎找不到正确的方法来做到这一点而不破坏流,腐败流标题等...

这是我目前的写法

private void writeData(SelectionKey key) throws IOException {
    Packet outPacket = null;
    synchronized (pendingPacketQue) {
        for (Packet packet : pendingPacketQue) {
            if (packet.getChannel().keyFor(selector).equals(key)) {
                outPacket = packet;
                break;
            }
        }
    }
    if (outPacket == null) {
        Logger.writeException("Couldn't find out bound packet in list.", LogType.SERVER);
        return;
    }
    SocketChannel connection = (SocketChannel) outPacket.getChannel();
    ObjectOutputStream outStream = new ObjectOutputStream(connection.socket().getOutputStream());
    outStream.writeObject(outPacket);
    outStream.flush();
    outStream.close();
    connection.keyFor(selector).interestOps(SelectionKey.OP_READ);
}

这是我目前的阅读方法

private void readData(SelectionKey key) throws IOException, ClassNotFoundException {
    SocketChannel connection = (SocketChannel) key.channel();
    buffer.clear();
    int byteCount;
    try {
        byteCount = connection.read(buffer);
    } catch (IOException e) {
        Logger.writeException("Connenction terminated.", LogType.SERVER);
        connection.close();
        key.cancel();
        return;
    }
    if (byteCount == -1) {
        Logger.writeException("Connection error. Terminating connection.", LogType.SERVER);
        key.channel().close();
        key.cancel();
        return;
    }
    Engine.getInstance().getPacketProcessor().processData(connection, buffer.array(), byteCount);
}

public void processData(SocketChannel connection, byte[] data, int count)
        throws IOException, ClassNotFoundException {
    ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
    ObjectInputStream inStream = new ObjectInputStream(byteStream);
    addToQue(inStream.readObject());
    inStream.close();
}

如果您有任何问题,请随时提出。谢谢!

1 个答案:

答案 0 :(得分:3)

您不必在一次阅读中阅读整个对象。

你也不能以这种方式写作。您无法在非阻塞模式下使用SocketChannel的套接字流。您应该在发件人中有IllegalBlockingModeException

因此很难看到当你不能在第一时间写任何东西时,你怎么可能已经达到了损坏的流标题等等。

无论如何,强烈建议您不要尝试这样做。这太难了。您需要在对象之前发送对象的大小,以便知道何时读取所有内容,发出多次读取并保存结果,直到您拥有所有内容,运行等等。使用java.net.Socket和正常的对象输入和输出流直接。