1 package com.slp.nio;
2
3 import org.junit.Test;
4
5 import java.io.IOException;
6 import java.net.InetSocketAddress;
7 import java.nio.ByteBuffer;
8 import java.nio.channels.SelectionKey;
9 import java.nio.channels.Selector;
10 import java.nio.channels.ServerSocketChannel;
11 import java.nio.channels.SocketChannel;
12 import java.time.LocalDateTime;
13 import java.util.Date;
14 import java.util.Iterator;
15 import java.util.Scanner;
16
17 /**
18 * Created by sanglp on 2017/3/2.
19 * 一、使用NIO完成网络通信的三个核心
20 * 1、通道:负责连接
21 * |--java.nio.channels.channel接口
22 * |--SelectableChannel
23 * |--SocketChannel
24 * |--ServerSocketChannel
25 * |--DatagramChannel
26 *
27 * |--Pipe.SinkChannel
28 * |--Pipe.SourceChannel
29 * 2、缓冲区:负责数据的存取
30 * 3、选择器:是SelectableChannel的多路复用器,用于监控SelectableChannel的IO状况
31 *
32 */
33 public class TestNonBlockingNIO {
34
35 @Test
36 public void client() throws IOException {
37 //获取通道
38 SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",9898));
39 //切换为非阻塞模式
40 socketChannel.configureBlocking(false);
41 //分配缓冲区
42 ByteBuffer buf = ByteBuffer.allocate(1024);
43 //发送数据给服务端
44
45 Scanner scanner = new Scanner(System.in);
46 while (scanner.hasNext()){
47 String str = scanner.next();
48 buf.put((new Date().toString()+"\n"+str).getBytes());
49 buf.flip();
50 socketChannel.write(buf);
51 buf.clear();
52 }
53
54
55 //关闭通道
56 socketChannel.close();
57
58 }
59
60 @Test
61 public void server() throws IOException {
62 //获取通道
63 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
64 //切换非阻塞模式
65 serverSocketChannel.configureBlocking(false);
66 //绑定连接
67 serverSocketChannel.bind(new InetSocketAddress(9898));
68 //获取一个选择器
69 Selector selector = Selector.open();
70 //将通道注册到选择器上 并且指定监听接收事件
71 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
72 //轮询式的获取选择器上已经准备就绪的事件
73 while (selector.select()>0){
74 //获取当前选择器中所有注册的选择键(已就绪的监听事件)
75 Iterator<SelectionKey> it = selector.selectedKeys().iterator();
76 while (it.hasNext()){
77 //获取准备就绪的事件
78 SelectionKey sk = it.next();
79 //判断具体是什么事件准备就绪
80 if(sk.isAcceptable()){
81 //获取额护短连接
82 SocketChannel socketChannel = serverSocketChannel.accept();
83 //切换非阻塞模式
84 socketChannel.configureBlocking(false);
85 //将该通道注册到选择器上
86 socketChannel.register(selector,SelectionKey.OP_READ);
87 }else if(sk.isReadable()){
88 //获取当前选择器上读就绪状态的通道
89 SocketChannel socketChannel = (SocketChannel) sk.channel();
90 //读取数据
91 ByteBuffer buffer = ByteBuffer.allocate(1024);
92 int len =0;
93 while ((len=socketChannel.read(buffer))>0){
94 buffer.flip();
95 System.out.println(new String(buffer.array(),0,len));
96 buffer.clear();
97 }
98 }
99 //取消选择键
100 it.remove();
101 }
102 }
103 }
104 }