JavaNIOSocketchannel仅在关闭输出后发送数据。为什么会这样?
好的,所以我试图编写一个程序,它接受JavaNIOSocketchannel连接,但也保持它们的开放性。因此,假设客户端发送了一条消息,那么服务器应该立即将相同的消息发送回(简单的Echo服务器),但应答过程不起作用,如果客户端发送新消息,服务器将不会响应,直到我关闭客户端的socketchannel。但在我关闭客户端通道后,所有先前发送的消息都将一次性送达。(对不起,我的英语不好,它不是我的母语) 编写过程用于服务器端和客户端 写作过程:JavaNIOSocketchannel仅在关闭输出后发送数据。为什么会这样?,java,sockets,io,nio,socketchannel,Java,Sockets,Io,Nio,Socketchannel,好的,所以我试图编写一个程序,它接受JavaNIOSocketchannel连接,但也保持它们的开放性。因此,假设客户端发送了一条消息,那么服务器应该立即将相同的消息发送回(简单的Echo服务器),但应答过程不起作用,如果客户端发送新消息,服务器将不会响应,直到我关闭客户端的socketchannel。但在我关闭客户端通道后,所有先前发送的消息都将一次性送达。(对不起,我的英语不好,它不是我的母语) 编写过程用于服务器端和客户端 写作过程: try {
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();
阅读过程:
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();
密钥选择过程(自动关闭返回false):
private void handleKeys(最终服务器socketchannel服务器socketchannel、设置键、HashMap会话)引发异常{
final Iterator Iterator=keys.Iterator();
while(iterator.hasNext()){
final SelectionKey SelectionKey=iterator.next();
iterator.remove();
if(selectionKey.isValid()){
如果(selectionKey.isAcceptable()){
final ServerSocketChannel serverSocketChannel2=(ServerSocketChannel)selectionKey.channel();
final-SocketChannel-SocketChannel=serverSocketChannel2.accept();
socketChannel.configureBlocking(假);
socketChannel.register(selectionKey.selector(),selectionKey.OP_READ);
sessions.put(socketChannel,newbytebuilder());
}else if(selectionKey.isReadable()){
最终SocketChannel SocketChannel=(SocketChannel)selectionKey.channel();
final ByteBuffer ByteBuffer=ByteBuffer.allocate(Connection.MAX\u BUFFER\u SIZE);
最终整数bytesRead=socketChannel.read(byteBuffer);
如果(字节读取!=-1){
字节[]数据=新字节[字节读取];
System.arraycopy(byteBuffer.array(),0,数据,0,字节读取);
布尔自动关闭=真;
if(ConnectionHost.this.handle(this.getConnectionCreator().createConnection(socketChannel),数据)){
自动关闭=真;
}否则自动关闭=错误;
如果(自动关闭){
会话。移除(socketChannel);
socketChannel.close();
}否则{
if(!sessions.containsKey(socketChannel))sessions.put(socketChannel,new ByteBuilder());
}
}
}else抛出新的BloumException(“不支持给定的键”);
}否则抛出新的BloumException(“密钥不再有效”);
}
}
问题其实很简单,经过一番尝试,我终于找到了解决办法。我忘了在阅读过程中添加中断语句。我还添加了一个简单的算法,可以删除1gb字节缓冲区导致的0字节
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());
}
final ArrayList<Byte> bytes = new ArrayList<>();
Integer current = 0;
for(Integer i = 0; i<byteBuffer.array().length; i++){
final byte b = byteBuffer.array()[i];
if(b==0){
Boolean okay = false;
for(Integer x = i+1; x<byteBuffer.array().length; x++){
if(byteBuffer.array()[x]!=0){
okay=true;
break;
}
}
if(!okay){
break;
}
bytes.add(b);
}else bytes.add(b);
current=current+1;
}
return this.toPrimitive(bytes.toArray(new Byte[bytes.size()]));
final ByteBuffer ByteBuffer=ByteBuffer.allocate(DefaultConnectionCreator.this.getDefaultBufferSize());
试一试{
while(socketChannel.read(byteBuffer)!=-1{
//byteBuffer.clear();
}
}捕获(IOException异常){
异常。printStackTrace();
抛出新的BloumException(exception.getMessage());
}
最终ArrayList字节数=新ArrayList();
整数电流=0;
对于(整数i=0;i你好,你有很多错误
写入前需要翻转缓冲区
如果读取为-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,
缓冲区限制())
这是因为在对数据执行任何操作之前,您一直在读取到流的末尾。与SocketChannel
的发送无关。在处理任何数据之前,此代码仍将读取到流的末尾,这是这里的实际问题。删除零的循环仅存在于此,因为他已丢弃了read()
,这会告诉他停在哪里。