NIO网络通信

来源:互联网 发布:自然语言处理余弦算法 编辑:程序博客网 时间:2024/05/17 09:07

NIO非阻塞式网络通信

1.简单介绍

阻塞式:客户端发送请求给服务端,服务端不能确定客户端发过来的数据真实有效时,这个线程会阻塞,此时服务端的线程等待。当客户端发送大量数据时,服务端使用多个线程进行数据传输。(使用多线程解决IO阻塞问题)即使是使用多线程,那么一个服务器的线程数量还是有效的,一旦有阻塞就无法做其他事情。这就是传统IO的阻塞问题。
非阻塞式: 添加了选择器,将每个通道注册到该选择器上,(选择器的作用是监控通道的IO状况(读,写,连接等等))。选择器会实时监控通道的状态,某个通道上的请求事件完全准备就绪,选择器才会将任务分配到服务端的一个或者多个线程去运行。如果客户端的请求没有准备就绪,服务器断的线程完全可以做其他事情。

这里写图片描述

TCP:

package jnio;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.Date;import java.util.Iterator;import org.junit.Test;public class TestNoBlockingNIO {    @Test    public void server() throws IOException {        // 获取通道        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();        //设置非阻塞模式        serverSocketChannel.configureBlocking(false);        // 绑定链接        serverSocketChannel.bind(new InetSocketAddress(7777));        // 获取选择器        Selector selector = Selector.open();        // 将通道注册到选择器上.SelectionKey为选择键,监控什么状态        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);        // 轮循式的获取准备事件        while (selector.select() > 0) {            //获取当前选择器中所有注册的选择键(已就绪的)            Iterator<SelectionKey> iterable = selector.selectedKeys()                    .iterator();            //迭代获取            while(iterable.hasNext()){                SelectionKey selectionKey = iterable.next();                //判断是什么准备事件                if (selectionKey.isAcceptable()) {                    SocketChannel socketChannel = serverSocketChannel.accept();                    //将客户端的链接切换成非阻塞模式                    socketChannel.configureBlocking(false);                    //将该通道注册到选择器上                    socketChannel.register(selector, SelectionKey.OP_READ);                }else if(selectionKey.isReadable()){                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();                    ByteBuffer buffer = ByteBuffer.allocate(1024);                    int len = 0;                    while((len = socketChannel.read(buffer))!=-1){                        buffer.flip();                        System.out.println(new String(buffer.array(),0,len));                        buffer.clear();                    }                }            }            //取消选择键            iterable.remove();        }    }    @Test    public void client() throws IOException {        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(                "127.0.0.1", 7777));        // 切换成非阻塞模式        socketChannel.configureBlocking(false);        ByteBuffer buffer = ByteBuffer.allocate(1024);        buffer.put(new Date().toString().getBytes());        buffer.flip();        socketChannel.write(buffer);        buffer.clear();        socketChannel.close();    }}

UDP:

package jnio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.DatagramChannel;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.util.Date;import java.util.Iterator;import java.util.Scanner;import org.junit.Test;public class Udp {    @Test    public void send() throws IOException{        DatagramChannel datagramChannel = DatagramChannel.open();        datagramChannel.configureBlocking(false);        ByteBuffer buffer = ByteBuffer.allocate(1024);        Scanner scanner = new Scanner(System.in);        while(scanner.hasNext()){            String s = scanner.next();            buffer.put((new Date().toString()+" :"+s).getBytes());            buffer.flip();            datagramChannel.send(buffer, new InetSocketAddress("127.0.0.1",9999));            buffer.clear();        }        datagramChannel.close();    }    @Test    public void reciver() throws IOException{        DatagramChannel datagramChannel= DatagramChannel.open();        datagramChannel.configureBlocking(false);        datagramChannel.bind(new InetSocketAddress(9999));        Selector selector = Selector.open();        datagramChannel.register(selector,SelectionKey.OP_READ);        while(selector.select()>0){            Iterator<SelectionKey> iterator = selector.keys().iterator();            while(iterator.hasNext()){                SelectionKey selectionKey = iterator.next();                if (selectionKey.isReadable()) {                    ByteBuffer buffer = ByteBuffer.allocate(1024);                    datagramChannel.receive(buffer);                    buffer.flip();                    System.out.println(new String(buffer.array(),0,buffer.limit()));                    buffer.clear();                }            }            iterator.remove();        }    }}
原创粉丝点击