本文共 7237 字,大约阅读时间需要 24 分钟。
github源码:https://github.com/JolyouLu/JAVAIO.git
src\main\java\com\JolyouLu\nio\groupchat 文件夹下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(2000); //阻塞2秒监听,通道有没有事件发生 if (count > 0){ //返回>0 有事件要处理 //遍历selectedKeys集合 Iteratoriterator = selector.selectedKeys().iterator(); while (iterator.hasNext()){ //获取SelectionKey SelectionKey key = iterator.next(); if (key.isAcceptable()){ //如果通道发生,客户端连接事件 //为连接的客户端,生成socketChannel SocketChannel socketChannel = listenChannel.accept(); //切换非阻塞模式 socketChannel.configureBlocking(false); //把socketChannel注册到selector中,并监听读事件 socketChannel.register(selector,SelectionKey.OP_READ); //提示客户端连接上了 System.out.println(socketChannel.getRemoteAddress() + " 客户端 上线"); } if (key.isReadable()){ //如果通道发生,可读事件 //处理读 readData(key); } //清理读取的selectedKeys容器 防止重复处理 iterator.remove(); } } } }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(), "GBK"); //输出消息 System.out.println("from 客户端:"+ msg); //向其它客户端转发消息 sendInfoToOtherClients(msg,channel); } }catch (IOException e){ try { System.out.println(channel.getRemoteAddress() + " 离线了.."); //取消注册 key.cancel(); //关闭通道 channel.close(); } catch (IOException ioException) { ioException.printStackTrace(); } } } //转发消息给其它客户端(channel) private void sendInfoToOtherClients(String msg,SocketChannel self) throws IOException { System.out.println("服务器转发消息中..."); //遍历 所有的注册到Selector的SocketChannel排查self for (SelectionKey key : selector.keys()) { //取出通道 Channel targetChannel = key.channel(); //targetChanneld的类型是SocketChannel,并且targetChannel不是自己 if (targetChannel instanceof SocketChannel && targetChannel != self){ //转型 SocketChannel dest = (SocketChannel)targetChannel; //将来msg 存到buffer ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes("GBK")); //将来buffer的数据写入通道 dest.write(buffer); } } } public static void main(String[] args) { //初始化服务器对象 GroupChatServer chatServer = new GroupChatServer(); chatServer.listen(); }}
public class GroupChatClient { //定义相关属性 private final String HOST = "127.0.0.1"; //服务器IP private final int PORT = 6666; //服务器端口 private Selector selector; private SocketChannel socketChannel; private String username; //构造器,初始化 public GroupChatClient() { try { //得到选择器 selector = Selector.open(); //连接服务 socketChannel = SocketChannel.open(new InetSocketAddress(HOST,PORT)); //设置非阻塞 socketChannel.configureBlocking(false); //将来socketChannel注册到Selector,关注读事件 socketChannel.register(selector, SelectionKey.OP_READ); //得到username username = socketChannel.getLocalAddress().toString().substring(1); System.out.println(username + " is ok ..."); }catch (Exception e){ e.printStackTrace(); } } //向服务器发送消息 public void sendInfo(String info){ info = username + " 说:" + info; try { socketChannel.write(ByteBuffer.wrap(info.getBytes("GBK"))); }catch (IOException e){ e.printStackTrace(); } } //读取从服务器端回复的消息 public void readInfo(){ try { int readChannels = selector.select(2000); if (readChannels > 0){ //有可用的通道 Iteratoriterator = selector.selectedKeys().iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); if (key.isReadable()){ //得到相关的通道 SocketChannel socketChannel = (SocketChannel) key.channel(); //得到一个Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); //buffer 读取通道数据 socketChannel.read(buffer); //把读到缓冲区的数据转成字符串 String msg = new String(buffer.array()); System.out.println(msg.trim()); } iterator.remove(); } } }catch (IOException e){ e.printStackTrace(); } } public static void main(String[] args) { //启动客户端 GroupChatClient chatClient = new GroupChatClient(); //启动一个线程,每隔开3秒读取服务器发送的数据 new Thread(new Runnable() { @Override 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); } }}
设置启动参数,当前类可以同时运行多个
转载地址:http://cyxo.baihongyu.com/