java nio 客户端关闭

阅读: 评论:0

java nio 客户端关闭

java nio 客户端关闭

如此代码,服务器端读取客户端信息时,如果客户端正常关闭,出现循环读问题,CPU被占满。

package com.timerty.select;

import java.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.util.Iterator;

/**

* Created by zhubo on 2018/1/16.

*/

public class NIOServer {

private Selector selector;

public void initServer(int port) throws Exception{

//获得一个ServerSocket通道

ServerSocketChannel serverChannel = ServerSocketChannel.open();

//设置通道为非阻塞

// 该通道对于serverSocket绑定到port端口

serverChannel.socket().bind(new InetSocketAddress(port));

// 获得一选择器

this.selector = Selector.open();

//将通道管理器和该通道绑定,并未该通道注册selectionKey.OP_ACCEPT事件

//注册该事件后,当事件到达的时候,selector.select()会返回,

// 如果事件没有到达selector.select()会一直阻塞

}

public void listen() throws Exception{

System.out.println("start server ...");

// 轮训访问seletor

while(true){

//当注册事件到达时,方法返回,否则该方法会一直阻塞

selector.select();

// 获得selector中选中项的地带器,选中项为注册事件

Iterator iterator = this.selector.selectedKeys().iterator();

if(iterator.hasNext()){

SelectionKey key = ();

//删除已选的key 以防止重复处理

//客户端请求链接事件

if(key.isValid() && key.isAcceptable()){

System.out.println(&#");

ServerSocketChannel server = (ServerSocketChannel) key.channel();

//获取客户端链接的通道

SocketChannel channel = server.accept();

// 非阻塞模式

//channel.write(ByteBuffer.wrap(new String("Hello Client").getBytes()));

// 在客户端链接成功后,为了可以连接到客户端的信息,需要给通道设置读的权限

}else if(key.isValid() && key.isReadable()){

read(key);

}

}

}

}

private void read(SelectionKey key) throws Exception {

SocketChannel channel = (SocketChannel)key.channel();

ByteBuffer buffer = ByteBuffer.allocate(100);

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("server receive from client : "+msg);

ByteBuffer outBuffer = ByteBuffer.Bytes());

channel.write(outBuffer);

//key.cancel();

//channel.close();

}

public static void main(String[] args) throws Exception{

NIOServer server = new NIOServer();

server.initServer(8989);

server.listen();

}

}

[root@centos1 ~]# telnet 192.168.1.114 8989

Trying 192.168.

Connected to 192.168.1.114.

Escape character is '^]'.

^]

telnet> send ao

锟斤拷

kdf

kdfdd

ddquit

quit^]

telnet> quit

Connection closed.

[root@centos1 ~]# telnet 192.168.1.114 8989

Trying 192.168.

Connected to 192.168.1.114.

Escape character is '^]'.

^]

telnet> send ao

锟斤拷

abc

abcdd

dd^]

telnet> quit

Connection closed.

[root@centos1 ~]#

当我们telnet切断客户端链接时,会一直出发SocketChannel读就绪事件。会出现循环度问题。

需要我们手动对读取通道数据代码进行改写:

private void read(SelectionKey key) throws Exception {

SocketChannel channel = (SocketChannel)key.channel();

ByteBuffer buffer = ByteBuffer.allocate(100);

try{

int read = ad(buffer);

if(read > 0){

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("server receive from client : "+msg);

ByteBuffer outBuffer = ByteBuffer.Bytes());

channel.write(outBuffer);

}else if(read < 0){

System.out.println("channel closed");

channel.close();

key.cancel();

}else

;

}catch (Exception e){

System.out.println("channel exception closed");

channel.close();

key.cancel();

}

//key.cancel();

//channel.close();

}

这样不管,客户端异常关闭导致的服务器异常退出,还是 客户端正常关闭导致的循环读问题都不会出现

本文发布于:2024-02-02 08:11:11,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170683267042498.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:客户端   java   nio
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23