2、nio的例子实践

下面的例子,说明了,nio中的三大核心类的基本使用。buffer,channel,selector

  1 package com.shengsiyuan.nio;
  2 
  3 import org.junit.Test;
  4 
  5 import java.io.*;
  6 import java.net.*;
  7 import java.nio.ByteBuffer;
  8 import java.nio.IntBuffer;
  9 import java.nio.MappedByteBuffer;
 10 import java.nio.channels.*;
 11 import java.nio.channels.spi.SelectorProvider;
 12 import java.security.SecureRandom;
 13 import java.util.Arrays;
 14 import java.util.Iterator;
 15 import java.util.Set;
 16 
 17 public class NioTest1 {
 18 
 19     public static void main(String[] args) {
 20         IntBuffer intBuffer = IntBuffer.allocate(10);
 21 
 22         for (int i = 0; i < intBuffer.capacity(); i++) {
 23             int randomNumber = new SecureRandom().nextInt(20);
 24             intBuffer.put(randomNumber);
 25         }
 26 
 27         intBuffer.flip();//翻转,从写转到读状态
 28 
 29         while (intBuffer.hasRemaining()) {
 30             System.out.println(intBuffer.get());
 31         }
 32 
 33     }
 34 
 35     public void testBuffer() {
 36         IntBuffer intBuffer = IntBuffer.allocate(10);
 37 
 38         for (int i = 0; i < intBuffer.capacity(); i++) {
 39             int randomNumber = new SecureRandom().nextInt(20);
 40             intBuffer.put(randomNumber);
 41         }
 42 
 43         intBuffer.flip();//翻转,从写转到读状态
 44 
 45         while (intBuffer.hasRemaining()) {
 46             System.out.println(intBuffer.get());
 47         }
 48     }
 49 
 50     /**
 51       * @ClassName:      NioTest1
 52       * @Description:     描述  读文件
 53       * @Author:         
 54       * @CreateDate:     2019/8/27 21:26
 55       * @Version:        1.0
 56      */
 57     @Test
 58     public void testChannelRead() {
 59         try {
 60             FileInputStream fileInputStream = new FileInputStream("NioTest1.txt");
 61 
 62             FileChannel fileChannel = fileInputStream.getChannel();
 63 
 64             ByteBuffer byteBuffer = ByteBuffer.allocate(512);
 65 
 66             fileChannel.read(byteBuffer);
 67 
 68             byteBuffer.flip();
 69 
 70             while(byteBuffer.remaining() > 0) {
 71 
 72                 byte b = byteBuffer.get();
 73                 System.out.println("char is : " + (char) b);
 74 
 75                 if((char)b == 'e') {
 76                     byteBuffer.mark();
 77                 }
 78             }
 79 
 80             System.out.println(byteBuffer.position());
 81             System.out.println(byteBuffer.limit());
 82             System.out.println(byteBuffer.capacity());
 83 
 84             byteBuffer.reset();
 85 
 86 //            System.out.println(byteBuffer.mark());
 87             System.out.println(byteBuffer.position());
 88             System.out.println(byteBuffer.limit());
 89             System.out.println(byteBuffer.capacity());
 90 
 91 
 92             fileChannel.close();
 93             fileInputStream.close();
 94 
 95         } catch (Exception e) {
 96             e.printStackTrace();
 97         }
 98     }
 99 
100     /**
101       * @ClassName:      NioTest1
102       * @Description:     描述  写文件
103       * @Author:         
104       * @CreateDate:     2019/8/27 21:25
105       * @Version:        1.0
106      */
107     @Test
108     public void testChannelWrite() {
109         try{
110             FileInputStream fileInputStream = new FileInputStream("NioTest1.txt");
111             FileChannel fileChannel = fileInputStream.getChannel();
112 
113             FileChannel randowFileChannel = new RandomAccessFile(new File("NioTest1.txt"),"rw").getChannel();
114 
115             ByteBuffer byteBuffer = ByteBuffer.allocate(512);
116 
117             byte[] byteArr = "hello nio  nihao!".getBytes();
118 
119             byteBuffer.put(byteArr);
120 
121 
122             byteBuffer.flip();
123 
124 //            fileChannel.write(byteBuffer);
125 
126             randowFileChannel.write(byteBuffer);
127         }catch (Exception e) {
128             e.printStackTrace();
129         }
130     }
131 
132     /**
133       * @ClassName:      NioTest1
134       * @Description:     描述  读写文件
135       * @Author:         
136       * @CreateDate:     2019/8/27 21:25
137       * @Version:        1.0
138      */
139     @Test
140     public void testChannelReadAndWrite() {
141         try {
142             FileInputStream fileInputStream = new FileInputStream("input.txt");
143             FileOutputStream fileOutputStream = new FileOutputStream("out.txt");
144 
145             FileChannel inputFileChannel = fileInputStream.getChannel();
146             FileChannel outputFileChannel = fileOutputStream.getChannel();
147 
148             ByteBuffer byteBuffer = ByteBuffer.allocate(512);
149 
150             while(inputFileChannel.read(byteBuffer) != -1) {
151 
152                 byteBuffer.flip();
153 
154                 outputFileChannel.write(byteBuffer);
155 
156 //                byteBuffer.clear();
157             }
158 
159         }catch (Exception e) {
160             e.printStackTrace();
161         }
162 
163     }
164 
165     /**   
166       * @ClassName:      NioTest1
167       * @Description:     描述  切下部分的byteBuffer 作为一个快照,可以实现同步
168       * @Author:         
169       * @CreateDate:     2019/8/27 21:24
170       * @Version:        1.0
171      */
172     @Test
173     public void testSlice() {
174         try{
175             ByteBuffer byteBuffer = ByteBuffer.allocate(512);
176 
177             for (int i = 0; i < 20; i++) {
178                 byteBuffer.put((byte)i);
179             }
180 //            byteBuffer.flip();
181 
182             ByteBuffer newByteBuffer = byteBuffer.slice();
183 
184             byteBuffer.put((byte)'a');
185             byteBuffer.put((byte)'b');
186 
187 //            newByteBuffer.flip();
188             System.out.println(newByteBuffer.get(0));
189 
190 //            byteBuffer.put(0, (byte)9);
191 
192             newByteBuffer.put(0, (byte)9);
193 
194             System.out.println(byteBuffer.get(20));
195 
196             System.out.println(newByteBuffer.get(0));
197 
198 
199         }catch (Exception e) {
200             e.printStackTrace();
201         }
202     }
203 
204     /**   
205       * @ClassName:      NioTest1
206       * @Description:     描述  只读的byteBuffer
207       * @Author:         
208       * @CreateDate:     2019/8/27 21:24
209       * @Version:        1.0
210      */
211     @Test
212     public void testReadonlyBuffer() {
213 
214         ByteBuffer byteBuffer = ByteBuffer.allocate(512);
215         for (int i = 0; i < 10; i++) {
216             byteBuffer.put((byte)i);
217         }
218 
219         ByteBuffer readOnlyBuffer = byteBuffer.asReadOnlyBuffer();
220 
221         readOnlyBuffer.position(0);
222 
223         readOnlyBuffer.put((byte)1);
224 
225     }
226 
227     /**   
228       * @ClassName:      NioTest1
229       * @Description:     描述  通过直接内存,零拷贝来处理文件
230       * @Author:         
231       * @CreateDate:     2019/8/27 21:23
232       * @Version:        1.0
233      */
234     @Test
235     public void testChannelReadAndWriteDirect() {
236         try {
237             FileInputStream fileInputStream = new FileInputStream("input.txt");
238             FileOutputStream fileOutputStream = new FileOutputStream("out.txt");
239 
240             FileChannel inputFileChannel = fileInputStream.getChannel();
241             FileChannel outputFileChannel = fileOutputStream.getChannel();
242 
243             ByteBuffer byteBuffer = ByteBuffer.allocateDirect(512);
244 
245             while(inputFileChannel.read(byteBuffer) != -1) {
246 
247                 byteBuffer.flip();
248 
249                 outputFileChannel.write(byteBuffer);
250 
251                 byteBuffer.clear();
252             }
253 
254         }catch (Exception e) {
255             e.printStackTrace();
256         }
257 
258     }
259 
260     /**   
261       * @ClassName:      NioTest1  内存映射,来修改文件  而不操作buffer
262       * @Description:     描述 
263       * @Author:         
264       * @CreateDate:     2019/8/27 21:23
265       * @Version:        1.0
266      */
267     @Test
268     public void testMapBuffer() throws Exception {
269         RandomAccessFile randomAccessFile = new RandomAccessFile("NioTest1.txt", "rw");
270         FileChannel fileChannel = randomAccessFile.getChannel();
271 
272         MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
273 
274         mappedByteBuffer.put(0, (byte)'a');
275         mappedByteBuffer.put(3, (byte)'b');
276 
277         fileChannel.close();
278         randomAccessFile.close();
279     }
280 
281 
282     /**
283       * @ClassName:      NioTest1
284       * @Description:     描述  测试 filelock
285       * @Author:         
286       * @CreateDate:     2019/8/27 21:30
287       * @Version:        1.0
288      */
289     @Test
290     public void testFilelock() throws Exception {
291         FileChannel fileChannel = new RandomAccessFile("NioTest1.txt", "rw").getChannel();
292 
293         FileLock fileLock = fileChannel.lock(3, 6, false);
294 
295         System.out.println(fileLock.isValid());
296         System.out.println(fileLock.isShared());
297     }
298 
299 
300     /**
301       * @ClassName:      NioTest1
302       * @Description:     描述
303       * @Author:         
304       * @CreateDate:     2019/8/27 22:36
305       * @Version:        1.0
306      */
307     @Test
308     public void testScattering() throws Exception {
309         ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
310         SocketAddress address = new InetSocketAddress(8899);
311         serverSocketChannel.bind(address);
312 
313         SocketChannel socketChannel = serverSocketChannel.accept();
314 
315         int messageLength = 2 + 3 +4;
316         ByteBuffer[] byteBuffers = new ByteBuffer[3];
317 
318         byteBuffers[0] = ByteBuffer.allocate(2);
319         byteBuffers[1] = ByteBuffer.allocate(3);
320         byteBuffers[2] = ByteBuffer.allocate(4);
321 
322         while(true) {
323             long readLength = 0;
324 
325             //最大读取 messageLength 长度的字符
326             while(readLength < messageLength ) {
327                 long r = socketChannel.read(byteBuffers);
328                 readLength += r;
329 
330                 System.out.println("byteBuffer length r is " + r);
331                 System.out.println("readLength length r is " + readLength);
332 
333                 Arrays.asList(byteBuffers).forEach(byteBuffer -> {
334                     System.out.println("p:" + byteBuffer.position() + ", l: " +byteBuffer.limit());
335                 });
336             }
337 
338             Arrays.asList(byteBuffers).forEach(byteBuffer -> {
339                 byteBuffer.flip();
340             });
341 
342             long writeLength = 0;
343             //写会去
344             while(writeLength < messageLength) {
345                 long w = socketChannel.write(byteBuffers);
346                 writeLength += w;
347                 System.out.println("byteBuffer length w is " + w);
348                 System.out.println("writeLength length w is " + writeLength);
349 
350                 Arrays.asList(byteBuffers).forEach(byteBuffer -> {
351                     System.out.println("p:" + byteBuffer.position() + ", l: " +byteBuffer.limit());
352                 });
353             }
354 
355             Arrays.asList(byteBuffers).forEach(byteBuffer -> byteBuffer.clear());
356 
357         }
358     }
359 
360     @Test
361     public void testSelector() throws  Exception{
362         Selector selector = Selector.open();
363 
364         int[] ports = {5000, 5001, 5002, 5003, 5004};
365 
366         for (int i = 0; i < ports.length; i++) {
367             ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
368             serverSocketChannel.configureBlocking(false); //变成非阻塞的模式 很重要
369 
370 //            serverSocketChannel.bind(new InetSocketAddress(ports[i]));
371 
372             ServerSocket serverSocket = serverSocketChannel.socket();
373             //这个bind 直接绑在 serverSocketChannel 可以不  尝试了下,好像区别不大,都可以走通  但是不能重复绑
374             serverSocket.bind(new InetSocketAddress(ports[i]));
375 
376             serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
377 
378             System.out.println("监听:" + ports[i]);
379         }
380 
381         while(true) {
382 
383             int number = selector.select();
384             System.out.println("number:" + number);
385 
386             Set<SelectionKey> selectionKeys = selector.selectedKeys();
387 
388             Iterator<SelectionKey> keyIterable = selectionKeys.iterator();
389 
390             System.out.println("selectionKeys : " + selectionKeys);
391 
392             while(keyIterable.hasNext()) {
393                 SelectionKey selectionKey = keyIterable.next();
394                 if(selectionKey.isAcceptable()) {//可接受的
395                     ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
396                     //这里为什么还要调accept  因为上面放进去的就是 ServerSocketChannel  ,而且没有调accept  接收请求
397                     SocketChannel socketChannel = serverSocketChannel.accept();
398                     socketChannel.configureBlocking(false);
399 
400                     System.out.println("获得链接:" + socketChannel);
401 
402                     socketChannel.register(selector, SelectionKey.OP_READ);
403 //                    socketChannel.register(selector, SelectionKey.OP_READ);  重复注册好像不影响
404 
405                     keyIterable.remove();//如果不remove  selectionKeys中会一直存在事件对象
406                 } else if(selectionKey.isReadable()) {//可读取的
407                     //这里就可以直接用SocketChannel来接收,因为在accept中,是用socketChannel来注册的
408                     SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
409 
410                     ByteBuffer byteBuffer = ByteBuffer.allocate(512);
411                     while(socketChannel.read(byteBuffer) > 0) {
412                         byteBuffer.flip();
413 
414                         System.out.println("读取到客户端的消息:" + byteBuffer);
415                         System.out.println("读取到客户端:" + socketChannel);
416 
417                         socketChannel.write(byteBuffer);
418 
419                         byteBuffer.clear();
420                     }
421 
422                     keyIterable.remove();
423 
424                 }
425 
426             }
427 
428         }
429 
430 
431     }
432 }

猜你喜欢

转载自www.cnblogs.com/amibandoufu/p/11441542.html