Netty学习笔记四:NIO实现群聊
群聊服务端代码
package com.mytest.netty.nio.groupChat; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; import java.util.Set; public class GroupChatServer { //定义相关属性 private Selector selector; private ServerSocketChannel listenChannel; private static final int PORT = 6666; //初始化工作 public GroupChatServer() { try{ //得到选择器 selector = Selector.open(); //得到ServerSocketChannel listenChannel = ServerSocketChannel.open(); //绑定端口 listenChannel.socket().bind(new InetSocketAddress(PORT)); //设置非阻塞模式 listenChannel.configureBlocking(false); //将listenChannel注册到selector上 listenChannel.register(selector, SelectionKey.OP_ACCEPT); }catch (IOException e) { e.printStackTrace(); } } //监听的代码 public void listen(){ try{ while (true) { int count = selector.select(); if (count > 0) {//有事件处理 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //取出selectionKey SelectionKey key = iterator.next(); //监听到accpet if (key.isAcceptable()) { SocketChannel sc = listenChannel.accept(); //设置非阻塞 sc.configureBlocking(false); //将该sc注册到selector sc.register(selector, SelectionKey.OP_READ); //给出上线提示 System.out.println(sc.getRemoteAddress() + "上线 "); } if (key.isReadable()) {//通道发生read事件 //处理读事件 readData(key); } //删除当前key,防止重复处理 iterator.remove(); } } else {//等待 System.out.println("等待中。。。。。"); } } } catch (Exception e) { e.printStackTrace(); } finally { } } //读取客户端消息 private void readData(SelectionKey key) { //定义一个socketChannel SocketChannel channel = null; try{ //得到channel channel = (SocketChannel) key.channel(); //创建Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); int count = channel.read(buffer); //根据count的值做处理 if (count > 0) { //将缓冲区的数据转为字符串并输出 String msg = new String(buffer.array()); //输出该消息 System.out.println(channel.getRemoteAddress() + ":" + msg); //向其他客户端转发消息(去掉自己) sendInfoToOtherClients(msg, channel); } } catch (IOException e) { try{ //处理发送过程中断开链接的情况 System.out.println(channel.getRemoteAddress() + "已离线。。。"); //取消注册 key.cancel(); //关闭通道 channel.close(); }catch (IOException e1) { e1.printStackTrace(); } } } //转发消息给其他客户(通道) private void sendInfoToOtherClients(String msg, SocketChannel self) throws IOException{ System.out.println("服务器消息发送中。。。"); for (SelectionKey key : selector.keys()) { //通过key, 去除对应的SocketChannel Channel targetChannel = key.channel(); //使用Channel也可以接受,因为SocketChannel实现了Channel //排除自己的Channel if (targetChannel instanceof SocketChannel && !self.equals(targetChannel)) { SocketChannel dest = (SocketChannel) targetChannel; //将msg 存储到Buffer ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); //将buffer的数据写入到通道中 dest.write(buffer); } } } public static void main(String[] args) { //创建一个服务器对象 GroupChatServer chatServer = new GroupChatServer(); //监听 chatServer.listen(); } }
客户端代码
package com.mytest.netty.nio.groupChat; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Scanner; public class GroupChatClient { //定义相关属性 private final String HOST = "127.0.0.1"; private static final int PORT = 6666; private Selector selector; private SocketChannel socketChannel; private String userName; //构造器 public GroupChatClient() throws IOException { selector = Selector.open(); //链接服务器 socketChannel = socketChannel.open(new InetSocketAddress(HOST, PORT)); //设置非阻塞 socketChannel.configureBlocking(false); //将channel注册到selector socketChannel.register(selector, SelectionKey.OP_READ); //得到userName userName = socketChannel.getLocalAddress().toString().substring(1); System.out.println(userName + "is ok ...."); } //向服务器发送消息 public void sendInfo(String info){ info = userName + "说:" + info; try{ socketChannel.write(ByteBuffer.wrap(info.getBytes())); } catch (IOException e) { e.printStackTrace(); } } //读取从服务端回复的数据 public void readInfo() { try { int readChannels = selector.select(2000); if (readChannels > 0) {//有可以使用的通道 Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if (key.isReadable()) { //得到相关的通道 SocketChannel sc = (SocketChannel) key.channel(); //得到一个Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); //读取 sc.read(buffer); System.out.println(new String(buffer.array())); } } iterator.remove(); }else { // System.out.println("没有可用的通道"); } }catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { //启动客户端 GroupChatClient chatClient = new GroupChatClient(); //启动一个线程,每隔3S读取从服务器端发送的数据 new Thread() { public void run() { while (true) { chatClient.readInfo(); try { Thread.currentThread().sleep(3000); }catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); //客户端发送数据给服务端 Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { String s = scanner.nextLine(); chatClient.sendInfo(s); } } }