NIO
2024-03-30 23:30 Spiderman25 阅读(8) 评论(0) 收藏 举报package com.spider.springcloud.io.nio; 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.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class NIOServer { public static void main(String[] args) throws IOException { //111111111 //Service端的Channel,监听端口的 ServerSocketChannel serverChannel = ServerSocketChannel.open(); //设置为非阻塞 serverChannel.configureBlocking(false); //nio的api规定这样赋值端口 serverChannel.bind(new InetSocketAddress(8000)); //显示Channel是否已经启动成功,包括绑定在哪个地址上 System.out.println("服务端启动成功,监听端口为8000,等待客户端连接..." + serverChannel.getLocalAddress()); //22222222 //声明selector选择器 Selector selector = Selector.open(); //这句话的含义,是把selector注册到Channel上面, //每个客户端来了之后,就把客户端注册到Selector选择器上,默认状态是Accepted serverChannel.register(selector, SelectionKey.OP_ACCEPT); //33333333 //创建buffer缓冲区,声明大小是1024,底层使用数组来实现的 ByteBuffer buffer = ByteBuffer.allocate(1024); //RequestHandler requestHandler = new RequestHandler(); //444444444 //轮询,服务端不断轮询,等待客户端的连接 //如果有客户端轮询上来就取出对应的Channel,没有就一直轮询 while (true) { int select = selector.select(); if (select == 0) { continue; } //有可能有很多,使用Set保存Channel Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { //使用SelectionKey来获取连接了客户端和服务端的Channel SelectionKey key = iterator.next(); //判断SelectionKey中的Channel状态如何,如果是OP_ACCEPT就进入 if (key.isAcceptable()) { //从判断SelectionKey中取出Channel ServerSocketChannel channel = (ServerSocketChannel) key.channel(); //拿到对应客户端的Channel SocketChannel clientChannel = channel.accept(); //把客户端的Channel打印出来 System.out.println("客户端通道信息打印:" + clientChannel.getRemoteAddress()); //设置客户端的Channel设置为非阻塞 clientChannel.configureBlocking(false); //操作完了改变SelectionKey中的Channel的状态OP_READ clientChannel.register(selector, SelectionKey.OP_READ); } //到此轮训到的时候,发现状态是read,开始进行数据交互 if (key.isReadable()) { //以buffer作为数据桥梁 SocketChannel channel = (SocketChannel) key.channel(); //数据要想读要先写,必须先读取到buffer里面进行操作 channel.read(buffer); //进行读取 String request = new String(buffer.array()).trim(); buffer.clear(); //进行打印buffer中的数据 System.out.println(String.format("客户端发来的消息: %s : %s", channel.getRemoteAddress(), request)); //要返回数据的话也要先返回buffer里面进行返回 // String response = requestHandler.handle(request); //然后返回出去 channel.write(ByteBuffer.wrap("response".getBytes())); } iterator.remove(); } } } }
package com.spider.springcloud.io.nio; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client01 { public static void main(String[] args) throws IOException { //创建套接字对象socket并封装ip与port Socket socket = new Socket("127.0.0.1", 8000); //根据创建的socket对象获得一个输出流 OutputStream outputStream = socket.getOutputStream(); //控制台输入以IO的形式发送到服务器 System.out.println("TCP连接成功 \n请输入:"); while(true){ byte[] car = new Scanner(System.in).nextLine().getBytes(); outputStream.write(car); System.out.println("TCP协议的Socket发送成功"); //刷新缓冲区 outputStream.flush(); } } }