我目前正在尝试通过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();
}
如果您有任何问题,请随时提出。谢谢!
答案 0 :(得分:3)
您不必在一次阅读中阅读整个对象。
你也不能以这种方式写作。您无法在非阻塞模式下使用SocketChannel
的套接字流。您应该在发件人中有IllegalBlockingModeException
。
因此很难看到当你不能在第一时间写任何东西时,你怎么可能已经达到了损坏的流标题等等。
无论如何,强烈建议您不要尝试这样做。这太难了。您需要在对象之前发送对象的大小,以便知道何时读取所有内容,发出多次读取并保存结果,直到您拥有所有内容,运行等等。使用java.net.Socket
和正常的对象输入和输出流直接。