NIO基本编写

一、编写server端

  1 public class Server implements Runnable{
  2     //1 多路复用器(管理所有的通道)
  3     private Selector seletor;
  4     //2 建立缓冲区
  5     private ByteBuffer readBuf = ByteBuffer.allocate(1024);
  6     //3 
  7     private ByteBuffer writeBuf = ByteBuffer.allocate(1024);
  8     public Server(int port){
  9         try {
 10             //1 打开路复用器
 11             this.seletor = Selector.open();
 12             //2 打开服务器通道
 13             ServerSocketChannel ssc = ServerSocketChannel.open();
 14             //3 设置服务器通道为非阻塞模式
 15             ssc.configureBlocking(false);
 16             //4 绑定地址
 17             ssc.bind(new InetSocketAddress(port));
 18             //5 把服务器通道注册到多路复用器上,并且监听阻塞事件
 19             ssc.register(this.seletor, SelectionKey.OP_ACCEPT);
 20             
 21             System.out.println("Server start, port :" + port);
 22             
 23         } catch (IOException e) {
 24             e.printStackTrace();
 25         }
 26     }
 27 
 28     @Override
 29     public void run() {
 30         while(true){
 31             try {
 32                 //1 必须要让多路复用器开始监听
 33                 System.out.println("1");
 34                 this.seletor.select();
 35                 System.out.println("2");
 36                 //2 返回多路复用器已经选择的结果集
 37                 Iterator<SelectionKey> keys = this.seletor.selectedKeys().iterator();
 38                 //3 进行遍历
 39                 System.out.println("keys"  + keys);
 40                 while(keys.hasNext()){
 41                     //4 获取一个选择的元素
 42                     SelectionKey key = keys.next();
 43                     //5 直接从容器中移除就可以了
 44                     keys.remove();
 45                     //6 如果是有效的
 46                     if(key.isValid()){
 47                         //7 如果为阻塞状态
 48                         if(key.isAcceptable()){
 49                             this.accept(key);
 50                         }
 51                         //8 如果为可读状态
 52                         if(key.isReadable()){
 53                             this.read(key);
 54                         }
 55                         //9 写数据
 56                         if(key.isWritable()){
 57                             //this.write(key); //ssc
 58                         }
 59 //                        key.isConnectable()
 60                     }
 61                     
 62                 }
 63             } catch (IOException e) {
 64                 e.printStackTrace();
 65             }
 66         }
 67     }
 68     
 69     private void write(SelectionKey key){
 70         //ServerSocketChannel ssc =  (ServerSocketChannel) key.channel();
 71         //ssc.register(this.seletor, SelectionKey.OP_WRITE);
 72     }
 73 
 74     private void read(SelectionKey key) {
 75         try {
 76             //1 清空缓冲区旧的数据
 77             this.readBuf.clear();
 78             //2 获取之前注册的socket通道对象
 79             SocketChannel sc = (SocketChannel) key.channel();
 80             //3 读取数据
 81             int count = sc.read(this.readBuf);
 82             //4 如果没有数据
 83             if(count == -1){
 84                 key.channel().close();
 85                 key.cancel();
 86                 return;
 87             }
 88             //5 有数据则进行读取 读取之前需要进行复位方法(把position 和limit进行复位)
 89             this.readBuf.flip();
 90             //6 根据缓冲区的数据长度创建相应大小的byte数组,接收缓冲区的数据
 91             byte[] bytes = new byte[this.readBuf.remaining()];
 92             //7 接收缓冲区数据
 93             this.readBuf.get(bytes);
 94             //8 打印结果
 95             String body = new String(bytes).trim();
 96             System.out.println("Server : " + body);
 97             
 98             // 9..可以写回给客户端数据 
 99         } catch (IOException e) {
100             e.printStackTrace();
101         }
102         
103     }
104 
105     private void accept(SelectionKey key) {
106         try {
107             //1 获取服务通道
108             ServerSocketChannel ssc =  (ServerSocketChannel) key.channel();
109             //2 执行阻塞方法
110             SocketChannel sc = ssc.accept();
111             System.out.println("阻塞");
112             //3 设置阻塞模式
113             sc.configureBlocking(false);
114             //4 注册到多路复用器上,并设置读取标识
115             sc.register(this.seletor, SelectionKey.OP_READ);
116         } catch (IOException e) {
117             e.printStackTrace();
118         }
119     }
120     
121     public static void main(String[] args) {
122         
123         new Thread(new Server(8765)).start();;
124     }

二、编写Client端

 1     public static void main(String[] args) {
 2         
 3         //创建连接的地址
 4         InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8765);
 5         
 6         //声明连接通道
 7         SocketChannel sc = null;
 8         
 9         //建立缓冲区
10         ByteBuffer buf = ByteBuffer.allocate(1024);
11         
12         try {
13             //打开通道
14             sc = SocketChannel.open();
15             //进行连接
16             sc.connect(address);
17             
18             while(true){
19                 //定义一个字节数组,然后使用系统录入功能:
20                 byte[] bytes = new byte[1024];
21                 System.in.read(bytes);
22                 
23                 //把数据放到缓冲区中
24                 buf.put(bytes);
25                 //对缓冲区进行复位
26                 buf.flip();
27                 //写出数据
28                 sc.write(buf);
29                 //清空缓冲区数据
30                 buf.clear();
31             }
32         } catch (IOException e) {
33             e.printStackTrace();
34         } finally {
35             if(sc != null){
36                 try {
37                     sc.close();
38                 } catch (IOException e) {
39                     e.printStackTrace();
40                 }
41             }
42         }
43         
44     }
posted @ 2022-02-23 13:46  xujf  Views(35)  Comments(0Edit  收藏  举报