客户端代码(可启动多个):
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Random; import java.util.Scanner; /** * @description: * @author:chenbin * @Date:2017/4/11 */ public class SendMessager { private Selector selector; private int code = new Random().nextInt(1000); // 定义实现编码、解码的字符集对象 private Charset charset = Charset.forName("UTF-8"); public static void main(String[] args) throws IOException { new SendMessager().init(); } public void init() throws IOException { //与远程端口建立连接 SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("127.0.0.1",9999)); //创建选择器,将channel注册到selector selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_CONNECT); //监听selector就绪事件 new ClientThread().start(); //创建键盘输入流 Scanner scan = new Scanner(System.in); while (scan.hasNextLine()) { //读取键盘输入 String line = code + "发出信息:" + scan.nextLine(); //将键盘输入的内容输出到SocketChannel中 socketChannel.write(charset.encode(line)); } } //定义读取服务器数据的线程 private class ClientThread extends Thread { public void run() { try { while (selector.select() > 0) { //遍历每个有可用IO操作Channel对应的SelectionKey for (SelectionKey sk : selector.selectedKeys()) { //删除正在处理的SelectionKey selector.selectedKeys().remove(sk); if(sk.isConnectable()){ SocketChannel sc = (SocketChannel)sk.channel(); //如果正在连接,则完成连接 if (sc.isConnectionPending()) { sc.finishConnect(); } sc.configureBlocking(false); sc.write(ByteBuffer.wrap(new String(code + "上线了").getBytes())); sc.register(selector,SelectionKey.OP_READ); } //如果该SelectionKey对应的Channel中有可读的数据 if (sk.isReadable()) { //使用NIO读取Channel中的数据 SocketChannel sc = (SocketChannel)sk.channel(); ByteBuffer buff = ByteBuffer.allocate(1024); String content = ""; while(sc.read(buff) > 0) { sc.read(buff); buff.flip(); content += charset.decode(buff); } //打印输出读取的内容 System.out.println(content); //为下一次读取作准备 sk.interestOps(SelectionKey.OP_READ); } } } } catch (IOException ex) { ex.printStackTrace(); } } } }
服务端代码:
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.util.Iterator; /** * @description: * @author:chenbin * @Date:2017/4/11 */ public class MessageReceriver { // 定义实现编码、解码的字符集对象 private Charset charset = Charset.forName("UTF-8"); public static void main(String[] args) throws IOException { //监听端口,创建socketChannel ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); serverChannel.socket().bind(new InetSocketAddress(9999)); //创建选择器,将channel注册到selector Selector selector = Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); new MessageReceriver().listen(selector); } private void listen(Selector selector) throws IOException { //获取selector就绪的事件 while (selector.select() > 0){ selector.select(); Iterator<SelectionKey> selectorKeys = selector.selectedKeys().iterator(); while (selectorKeys.hasNext()){ SelectionKey key = selectorKeys.next(); selectorKeys.remove(); if(key.isAcceptable()){ ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel sockerChannel = serverChannel.accept(); sockerChannel.configureBlocking(false); sockerChannel.register(selector,SelectionKey.OP_READ); } if(key.isReadable()){ SocketChannel socketChannel = (SocketChannel) key.channel(); socketChannel.configureBlocking(false); ByteBuffer byteBuffer = ByteBuffer.allocate(48); String content = ""; try { while (socketChannel.read(byteBuffer) > 0) { byteBuffer.flip(); content += charset.decode(byteBuffer); } System.out.println("=====" + content); key.interestOps(SelectionKey.OP_READ); }catch (Exception e){ key.cancel(); if(key.channel() != null){ key.channel().close(); } } // 如果content的长度大于0,即聊天信息不为空 if (content.length() > 0) { // 遍历该selector里注册的所有SelectKey for (SelectionKey key1 : selector.keys()) { // 获取该key对应的Channel Channel targetChannel = key1.channel(); // 如果该channel是SocketChannel对象 if (targetChannel instanceof SocketChannel) { // 将读到的内容写入该Channel中 SocketChannel dest = (SocketChannel) targetChannel; dest.write(charset.encode(content)); } } } } } } //对事件进行处理 } }