Java NIO Socketchannel 关闭输出后才发送数据。为什么是这样?
Java NIO Socketchannel only sends data after shutting down output. Why is this?
好吧,所以我正在尝试编写一个接受 java nio SocketChannel 连接但同时保持打开状态的程序。所以假设客户端发送一条消息,那么服务器应该立即发回相同的消息(简单回声服务器)但是应答过程不起作用,如果客户端发送一条新消息,服务器将不会响应,直到我关闭客户端的套接字通道.但是在我关闭客户端的频道后,所有以前发送的消息都会一次性进入。 (抱歉我的英语不好,这不是我的母语)
写入过程用于Server端和Client端。
编写过程:
try {
final ByteBuffer byteBuffer = ByteBuffer.wrap(data);
while(byteBuffer.hasRemaining()){
socketChannel.write(byteBuffer);
}
byteBuffer.flip();
} catch (IOException exception) {
throw new BloumException(exception.getMessage());
}
阅读过程:
final ByteBuffer byteBuffer = ByteBuffer.allocate(DefaultConnectionCreator.this.getDefaultBufferSize());
try {
while(socketChannel.read(byteBuffer) != -1){
//byteBuffer.clear();
}
} catch (IOException exception) {
exception.printStackTrace();
throw new BloumException(exception.getMessage());
}
return byteBuffer.array();
密钥选择过程(自动关闭Returns false):
private void handleKeys(final ServerSocketChannel serverSocketChannel, Set<SelectionKey> keys, HashMap<SocketChannel, ByteBuilder> sessions) throws Exception{
final Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()){
final SelectionKey selectionKey = iterator.next();
iterator.remove();
if(selectionKey.isValid()){
if(selectionKey.isAcceptable()){
final ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel)selectionKey.channel();
final SocketChannel socketChannel = serverSocketChannel2.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);
sessions.put(socketChannel, new ByteBuilder());
}else if(selectionKey.isReadable()){
final SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
final ByteBuffer byteBuffer = ByteBuffer.allocate(Connection.MAX_BUFFER_SIZE);
final Integer bytesRead = socketChannel.read(byteBuffer);
if(bytesRead!=-1){
byte[] data = new byte[bytesRead];
System.arraycopy(byteBuffer.array(), 0, data, 0, bytesRead);
Boolean autoClose = true;
if(ConnectionHost.this.handle(this.getConnectionCreator().createConnection(socketChannel), data)){
autoClose=true;
}else autoClose=false;
if(autoClose){
sessions.remove(socketChannel);
socketChannel.close();
}else{
if(!sessions.containsKey(socketChannel))sessions.put(socketChannel, new ByteBuilder());
}
}
}else throw new BloumException("The given key is not supported.");
}else throw new BloumException("The key is not valid anymore.");
}
}
您好,您那里有很多错误
- 写入前需要翻转缓冲区
- 如果读取为 -1,您 必须 关闭频道
- 不要创建 1GB 字节的缓冲区,使用的大小是 256、1024、4096、8196 我推荐 4096。
- 使用直接缓冲区,直接内存已证明自己对于 I/O 更快,因为它是
未被垃圾收集器中断
- 没有布尔值的 if 语句设置布尔值等于语句
- 不要有忽略读取字节的 while 循环,如果它是 0 就意味着你
没有任何可读的东西导致你循环直到套接字有
关闭
- 我很确定你在那里删除 0 的循环是为了
删除未添加的数据,但您可以这样做
Arrays.copyOfRange(buffer.array(), 0, buffer.position())
或者如果你
然后翻转缓冲区 Arrays.copyOfRange(buffer.array(), 0,
buffer limit())
好吧,所以我正在尝试编写一个接受 java nio SocketChannel 连接但同时保持打开状态的程序。所以假设客户端发送一条消息,那么服务器应该立即发回相同的消息(简单回声服务器)但是应答过程不起作用,如果客户端发送一条新消息,服务器将不会响应,直到我关闭客户端的套接字通道.但是在我关闭客户端的频道后,所有以前发送的消息都会一次性进入。 (抱歉我的英语不好,这不是我的母语)
写入过程用于Server端和Client端。
编写过程:
try {
final ByteBuffer byteBuffer = ByteBuffer.wrap(data);
while(byteBuffer.hasRemaining()){
socketChannel.write(byteBuffer);
}
byteBuffer.flip();
} catch (IOException exception) {
throw new BloumException(exception.getMessage());
}
阅读过程:
final ByteBuffer byteBuffer = ByteBuffer.allocate(DefaultConnectionCreator.this.getDefaultBufferSize());
try {
while(socketChannel.read(byteBuffer) != -1){
//byteBuffer.clear();
}
} catch (IOException exception) {
exception.printStackTrace();
throw new BloumException(exception.getMessage());
}
return byteBuffer.array();
密钥选择过程(自动关闭Returns false):
private void handleKeys(final ServerSocketChannel serverSocketChannel, Set<SelectionKey> keys, HashMap<SocketChannel, ByteBuilder> sessions) throws Exception{
final Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()){
final SelectionKey selectionKey = iterator.next();
iterator.remove();
if(selectionKey.isValid()){
if(selectionKey.isAcceptable()){
final ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel)selectionKey.channel();
final SocketChannel socketChannel = serverSocketChannel2.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);
sessions.put(socketChannel, new ByteBuilder());
}else if(selectionKey.isReadable()){
final SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
final ByteBuffer byteBuffer = ByteBuffer.allocate(Connection.MAX_BUFFER_SIZE);
final Integer bytesRead = socketChannel.read(byteBuffer);
if(bytesRead!=-1){
byte[] data = new byte[bytesRead];
System.arraycopy(byteBuffer.array(), 0, data, 0, bytesRead);
Boolean autoClose = true;
if(ConnectionHost.this.handle(this.getConnectionCreator().createConnection(socketChannel), data)){
autoClose=true;
}else autoClose=false;
if(autoClose){
sessions.remove(socketChannel);
socketChannel.close();
}else{
if(!sessions.containsKey(socketChannel))sessions.put(socketChannel, new ByteBuilder());
}
}
}else throw new BloumException("The given key is not supported.");
}else throw new BloumException("The key is not valid anymore.");
}
}
您好,您那里有很多错误
- 写入前需要翻转缓冲区
- 如果读取为 -1,您 必须 关闭频道
- 不要创建 1GB 字节的缓冲区,使用的大小是 256、1024、4096、8196 我推荐 4096。
- 使用直接缓冲区,直接内存已证明自己对于 I/O 更快,因为它是 未被垃圾收集器中断
- 没有布尔值的 if 语句设置布尔值等于语句
- 不要有忽略读取字节的 while 循环,如果它是 0 就意味着你 没有任何可读的东西导致你循环直到套接字有 关闭
- 我很确定你在那里删除 0 的循环是为了
删除未添加的数据,但您可以这样做
Arrays.copyOfRange(buffer.array(), 0, buffer.position())
或者如果你 然后翻转缓冲区Arrays.copyOfRange(buffer.array(), 0, buffer limit())