服务端:
public class NioServer { public static void main(String[] args) throws IOException { NioServer nioServer = new NioServer(); nioServer.nioDemo9(); } private Selector selector; private ServerSocketChannel serverSocketChannel; public NioServer() throws IOException { //先新建ServerSocketChannel来监听端口 serverSocketChannel = ServerSocketChannel.open(); //设置为非阻塞 serverSocketChannel.configureBlocking(false); //新建一个Selector selector = Selector.open(); //开始监听端口 InetSocketAddress inetSocketAddress = new InetSocketAddress(6666); //监听端口 serverSocketChannel.socket().bind(inetSocketAddress); //然后把ServerSocketChannel注册到selector中,并关心事件为accept serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); } public void nioDemo9() throws IOException { //开始进行监听后的操作,轮询等待客户端 while(true){ //判断是否有正在发生事件的通道 if (selector.select(1000)==0){ System.out.println("服务等待了一秒钟,无连接"); continue; } //如果返回的是大于0 ,则获取相关的selectionKey集合 Set<SelectionKey> selectionKeys = selector.selectedKeys(); //对这些key遍历进行业务操作 selectionKeys.stream().forEach(selectionKey -> { //如果改key是注册的意思,就先对其进行注册,处理连接 if (selectionKey.isAcceptable()){ try { //创建一个socketchannel为客户端所用 SocketChannel socketChannel = serverSocketChannel.accept(); System.out.println("有客户端进行连接:"+socketChannel.hashCode()); socketChannel.configureBlocking(false); //需要把socketchannel也注册到selector上 socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024)); System.out.println(socketChannel.getRemoteAddress()+"上线"); } catch (IOException e) { e.printStackTrace(); } }if (selectionKey.isReadable()){ //通道发生read事件,通道可读状态 //如果是可读的事件,则对其进行读取 try { //通过selectionKey来得到channel SocketChannel channel = (SocketChannel)selectionKey.channel(); //通过selectionKey来得到buffer ByteBuffer attachment = (ByteBuffer)selectionKey.attachment(); //将buffer的数据读到channel channel.read(attachment); String str = new String(attachment.array()); //写一个方法用来将信息发给其他客户端 System.out.println("from 客户端"+str); sendMsg(channel,str); } catch (IOException e) { e.printStackTrace(); } } }); } } public void sendMsg(SocketChannel self,String msg){ //得到所有的key Set<SelectionKey> selectionKeys = selector.selectedKeys(); selectionKeys.stream().forEach(key->{ //根据key得到Channel Channel channel = key.channel(); //然后判断是否为本socketchannel SocketChannel socketChannel = (SocketChannel) channel; if (self!=socketChannel){ if (self instanceof SocketChannel) { ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes()); try { socketChannel.write(byteBuffer); } catch (IOException e) { e.printStackTrace(); } } }else{ System.out.println("没有其他客户端进行连接"); } }); } }
客户端:
public class NioClient { // 定义相关的属性 private static final String HOST = "127.0.0.1"; // 服务器ip地址 private static final int PORT = 6666; // 服务器端口 private Selector selector; private SocketChannel socketChannel; private String userName; private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2)); public NioClient() { try { this.selector = Selector.open(); // 连接服务器 socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", PORT)); // 设置非阻塞 socketChannel.configureBlocking(false); // 将 channel 注册到 selector,事件 READ socketChannel.register(this.selector, SelectionKey.OP_READ); // 得到userName userName = socketChannel.getLocalAddress().toString().substring(1); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { // 启动客户端 NioClient client = new NioClient(); threadPoolExecutor.execute(new Runnable() { @Override public void run() { while(true){ try { // client.read(); client.send("test"); TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); break; } } } }); } private static void nioDemo10() throws IOException { //新建一个客户端使用的socketchannel SocketChannel socketChannel = SocketChannel.open(); //设置为非阻塞channel socketChannel.configureBlocking(false); //连接上服务端的6666端口 InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 6666); //开始连接 boolean connect = socketChannel.connect(socketAddress); if (!connect) { //没连接上,然后判断连接是否已经中断,如果还没有中断,则提示 while (!socketChannel.finishConnect()) { System.out.println("连接还未中断,可以进行其他操作"); } } else { //连接成功,开始发送信息 String str = "客户端发送信息为1"; //这里ByteBuffer提供了一个方法,避免了资源浪费,以往是使用allocal方法来开启一个有大小的buffer //这里的wrap方法是可以根据byte数组的大小来定义buffer的大小的,这样不会造成资源浪费 ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes()); //nio里面的传输数据,就是把buffer里面的数据,写入到channel就行了 socketChannel.write(byteBuffer); System.in.read(); } } /** * 发送数据到服务器 * @param msg */ private void send(String msg) { msg = userName + ":" + msg; ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8)); try { socketChannel.write(buffer); } catch (IOException e) { e.printStackTrace(); } } /** * @description 从通道读取数据并显示 * @author * @date */ private void read() throws IOException { selector.select(); // 存在可用通道,读取数据并显示 (注意这里是 selector.selectedKeys() 而不是 selector.keys() ) Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); // 若可读通道,则读取 if (key.isReadable()) { SocketChannel sc = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int count = sc.read(buffer); System.out.println(new String(buffer.array(), 0, count , StandardCharsets.UTF_8)); } // 用完key要移除 iterator.remove(); } } }