依次通道写发送的java.nio中的已损坏的数据

问题描述 投票:1回答:2

我有一个使用非阻塞套接字,NIO的服务器。服务器在一个单独的线程工作,并有一个名为游戏另一个线程。游戏线程保持服务器对象,并使用server.sendMessage,服务器线程仅读取数据。当我打电话的sendMessage两次相继在while循环2包,片刻后,我得到“java.io.StreamCorruptedException:无效的流头:6B6574B4”错误的客户端。

服务器代码的一部分:

public void write(SelectionKey channelKey, byte[] buffer) {
    if (buffer != null) {
        int bytesWritten;
        try {
            SocketChannel channel = (SocketChannel) channelKey.channel();
            synchronized (channel) {
                bytesWritten = channel.write(ByteBuffer.wrap(buffer));
            }
            if (bytesWritten == -1) {
                resetKey(channelKey);
                disconnected(channelKey);
            }
        } catch (Exception e) {
            resetKey(channelKey);
            disconnected(channelKey);
        }
    }
}

public void broadcast(byte[] buf, SelectionKey fr) {
    synchronized (clientList) {
        Iterator<SelectionKey> i = clientList.iterator();
        while (i.hasNext()) {
            SelectionKey key = i.next();
            if (fr != key)
                write(key, buf);
        }
    }
}

public synchronized void sendMessage(Packets pk) {
    broadcast(pk.toByteArray(), null);
}
java serialization nio
2个回答
1
投票

我猜(从已包含的代码量小),就是你不划定您的邮件在所有。即使你单独发送2个消息中,IO层可以分割/结合那些以各种方式使得接收器获取附加到先前消息的一个消息的一部分。应该使用某种“消息”协议来向接收机指示究竟有多少字节要消耗,以便它可以正确地分析每个进入的消息(例如写消息字节长度的第一,则该消息字节)。

作为一个侧面说明,write()方法不能保证写入的所有字节一个电话,所以你应该处理的返回值,并根据需要编写其余的字节。


1
投票

你需要编写,并flip()compact()之后,你需要停止假设一个write()写入整个缓冲区。它返回的一个原因的值。您需要循环,或者如果您在非阻塞模式是你需要进行如下:

  1. 写。
  2. 如果写没有完全完成,注册渠道OP_WRITE,并返回到选择循环。
  3. 当信道变为可写,再次尝试写,如果仍然没有完成只是不断循环。
  4. 否则注销OP_WRITE。
© www.soinside.com 2019 - 2024. All rights reserved.