java使用selector NIO socket
来源:互联网 发布:贝云cms 编辑:程序博客网 时间:2024/05/11 23:01
使用NIO的socket时 一直测试状态是 服务端返回的信息所有客户端都能收到 一直很郁闷 后来发现 是服务端代码的问题 在接受到一个channel时 我的代码里是拿select又做了一次遍历 对所有的客户端进行返回
下面给一个代码示例
服务端
public class HansServer { // 用于检测所有Channel状态的Selector private Selector selector = null; public void init() throws IOException { selector = Selector.open(); // 通过open方法来打开一个未绑定的ServerSocketChannel实例 ServerSocketChannel server = ServerSocketChannel.open(); InetSocketAddress isa = new InetSocketAddress("127.0.0.1", 30000); // 将该ServerSocketChannel绑定到指定IP地址 server.socket().bind(isa); // 设置ServerSocket以非阻塞方式工作 server.configureBlocking(false); // 将server注册到指定Selector对象 server.register(selector, SelectionKey.OP_ACCEPT); while (selector.select() > 0) { // 依次处理selector上的每个已选择的SelectionKey for (SelectionKey sk : selector.selectedKeys()) { // 从selector上的已选择Key集中删除正在处理的SelectionKey selector.selectedKeys().remove(sk); // 如果sk对应的通道包含客户端的连接请求 if (sk.isAcceptable()) { // 调用accept方法接受连接,产生服务器端对应的SocketChannel ServerSocketChannel ssc =(ServerSocketChannel) sk.channel(); SocketChannel sc = ssc.accept();// SocketChannel sc = server.accept(); // 设置采用非阻塞模式 sc.configureBlocking(false); // 将该SocketChannel也注册到selector sc.register(selector, SelectionKey.OP_READ); } // 如果sk对应的通道有数据需要读取 if (sk.isReadable()) { // 获取该SelectionKey对应的Channel,该Channel中有可读的数据 SocketChannel sc = (SocketChannel) sk.channel(); // 定义准备执行读取数据的ByteBuffer ByteBuffer buff = ByteBuffer.allocate(1024); String content = ""; byte[] receData =new byte[0]; byte[] temp =new byte[1]; // 开始读取数据 try { while(sc.read(buff)> 0){ sc.read(buff); buff.flip(); int limit = buff.limit(); temp =new byte[limit]; buff.get(temp,0,limit); byte[] and = new byte[temp.length+receData.length]; System.arraycopy(receData, 0, and, 0, receData.length); System.arraycopy(temp, 0, and, receData.length, temp.length); receData=and; buff.clear(); } content += StandardCharsets.UTF_8.decode(ByteBuffer.wrap(receData)); if(sc.read(buff) == -1){ System.out.println("断开..." + sc.socket().getRemoteSocketAddress()); sk.cancel(); if (sk.channel() != null) { sk.channel().close(); sc.close(); } }else{ // 打印从该sk对应的Channel里读取到的数据 System.out.println("=====接收到客户端数据:" + content); if (content.length() > 0) { sc.write(StandardCharsets.UTF_8.encode("服务端发送:"+content+"---已收到!!!")); } } } // 如果捕捉到该sk对应的Channel出现了异常,即表明该Channel // 对应的Client出现了问题,所以从Selector中取消sk的注册 catch (IOException ex) { // 从Selector中删除指定的SelectionKey sk.cancel(); if (sk.channel() != null) { sk.channel().close(); sc.close(); } } // 如果content的长度大于0,即聊天信息不为空// if (content.length() > 0) {//// // 遍历该selector里注册的所有SelectKey//// for (SelectionKey key : selector.keys()) {//// // 获取该key对应的Channel//// Channel targetChannel = key.channel();//// // 如果该channel是SocketChannel对象//// if (targetChannel instanceof SocketChannel) {//// // 将读到的内容写入该Channel中//// SocketChannel dest = (SocketChannel) targetChannel;//// dest.write(StandardCharsets.UTF_8.encode("服务端发送:"+content+"---已收到!!!"));//// }//// }// } } } } } public static void main(String[] args) throws IOException { new HansServer().init(); }}
客户端
public class HansClient { // 定义检测SocketChannel的Selector对象 private Selector selector = null; // 客户端SocketChannel private SocketChannel sc = null; public void init() throws IOException { selector = Selector.open(); InetSocketAddress isa = new InetSocketAddress("127.0.0.1", 30000); // 调用open静态方法创建连接到指定主机的SocketChannel sc = SocketChannel.open(isa); // 设置该sc以非阻塞方式工作 sc.configureBlocking(false); // 将SocketChannel对象注册到指定Selector sc.register(selector, SelectionKey.OP_READ); // 创建键盘输入流// Scanner scan = new Scanner(System.in);// while (scan.hasNextLine()) { // 读取键盘输入 int SendRes = new HansClient().S_SendData(sc); System.out.println("发送数据返回值"+SendRes);// } // 启动读取服务器端数据的线程// new ClientThread().start(); new HansClient().S_ResData(selector); sc.close(); selector.close(); } public int S_SendData(SocketChannel sc ){ int sendRes =0; String line = "6*7"; // 将键盘输入的内容输出到SocketChannel中 try { sendRes = sc.write(StandardCharsets.UTF_8.encode(line));} catch (IOException e) {e.printStackTrace();} return sendRes; } public void S_ResData(Selector sele){ try { while (sele.select() > 0) { // 遍历每个有可用IO操作Channel对应的SelectionKey for (SelectionKey sk : sele.selectedKeys()) { // 删除正在处理的SelectionKey sele.selectedKeys().remove(sk); // 如果该SelectionKey对应的Channel中有可读的数据 if (sk.isReadable()) { // 使用NIO读取Channel中的数据 SocketChannel sc = (SocketChannel) sk.channel(); ByteBuffer buff = ByteBuffer.allocate(5); String content = ""; byte[] receData =new byte[0]; byte[] temp =new byte[1]; while(sc.read(buff)> 0){ sc.read(buff); temp = buff.array(); byte[] and = new byte[temp.length+receData.length]; System.arraycopy(receData, 0, and, 0, receData.length); System.arraycopy(temp, 0, and, receData.length, temp.length); receData=and; buff.flip(); buff.clear(); } content += StandardCharsets.UTF_8.decode(ByteBuffer.wrap(receData)); // 打印输出读取的内容 System.out.println("聊天信息:" + content); break; } } break; } } catch (IOException ex) { ex.printStackTrace(); } }
public static void main(String[] args) throws IOException { new HansClient().init(); }}
阅读全文
0 0
- java使用selector NIO socket
- Java Socket:Java-NIO-Selector
- java nio selector的使用
- java nio Selector的使用-服务器端
- java nio Selector的使用-客户端
- java nio Selector的使用-服务器端
- java nio Selector的使用-服务器端
- java nio Selector的使用-客户端
- java nio Selector的使用-服务器端
- java nio Selector的使用-客户端
- Java NIO之Selector的使用
- nio selector简单使用
- Java NIO Selector
- JAVA NIO之selector
- Java NIO(7-Selector)
- Java NIO Selector
- Java NIO Selector
- java NIO- Selector
- 《java与模式》-3 设计原则
- Wamp里Apche启动失败
- Storm之——单机环境部署
- 安装angular
- 机器学习常用分类模型特点总结
- java使用selector NIO socket
- js变量和对象的索引
- NOJ(1001)-递归与分治算法-二分查找
- 防止sql注入 xss攻击
- 实验之顺序队列
- 作业
- 关于Mac os gradle 编译时报‘could not download gradle.jar…’的错误问题解决
- TOJ2333 Feel Good
- Java8 I/O源码-CharArrayReader与CharArrayWriter