博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NIO阻塞与非阻塞IO
阅读量:6847 次
发布时间:2019-06-26

本文共 5067 字,大约阅读时间需要 16 分钟。

一、使用NIO完成网络通信的三个核心

1、通道(Channel):负责连接
java.nio.channels.Channel 接口
|– SelectableChannel
|– SocketChannel
|–ServerChannel
|–DatagramChannel
|–Pipe.SinkChannel
|–Pipe.SourceChannel

2、缓冲区(Buffer): 负责数据的存取

3、选择器(Selector): 是SelectableChannel 的多路复用器,用于监控SelectableChannel 的IO状况

阻塞

package nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.file.Paths;import java.nio.file.StandardOpenOption;import org.junit.Test;public class TestBlockingNIO {    @Test    public void client() throws IOException{        //1、获取通道        SocketChannel sChannel=SocketChannel.open(new InetSocketAddress("127.0.0.1",9898));        FileChannel inChannel=FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);        //2、获取指定大小的缓冲区域        ByteBuffer buf=ByteBuffer.allocate(1024);        //3、读取本地文件,并发送到服务端去        while(inChannel.read(buf)!=-1){            buf.flip();            sChannel.write(buf);            buf.clear();        }        //4、关闭通道        inChannel.close();        sChannel.close();    }    @Test    public void server() throws IOException{        //1、获取通道        ServerSocketChannel ssChannel=ServerSocketChannel.open();        FileChannel outChannel=FileChannel.open(Paths.get("2.jpg"),StandardOpenOption.WRITE,StandardOpenOption.CREATE);        //2、绑定连接        ssChannel.bind(new InetSocketAddress(9898));        //3、获取客户端连接的通道        SocketChannel sChannel=ssChannel.accept();        //4、分配指定大小的缓冲区        ByteBuffer buf=ByteBuffer.allocate(1024);        //5、接受客户端的数据,并保存到本地        while(sChannel.read(buf)!=-1){            buf.flip();            outChannel.write(buf);            buf.clear();        }        //6、关闭通道        sChannel.close();        ssChannel.close();        outChannel.close();    }}

非阻塞

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 java.util.Scanner;import org.junit.Test;/* * 一、使用 NIO 完成网络通信的三个核心: *  * 1. 通道(Channel):负责连接 *       *     java.nio.channels.Channel 接口: *          |--SelectableChannel *              |--SocketChannel *              |--ServerSocketChannel *              |--DatagramChannel *  *              |--Pipe.SinkChannel *              |--Pipe.SourceChannel *  * 2. 缓冲区(Buffer):负责数据的存取 *  * 3. 选择器(Selector):是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况 *  */public class TestNonBlockingNIO {
//客户端 @Test public void client() throws IOException{ //1. 获取通道 SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898)); //2. 切换非阻塞模式 sChannel.configureBlocking(false); //3. 分配指定大小的缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); //4. 发送数据给服务端 Scanner scan = new Scanner(System.in); while(scan.hasNext()){ String str = scan.next(); buf.put((new Date().toString() + "\n" + str).getBytes()); buf.flip(); sChannel.write(buf); buf.clear(); } //5. 关闭通道 sChannel.close(); } //服务端 @Test public void server() throws IOException{ //1. 获取通道 ServerSocketChannel ssChannel = ServerSocketChannel.open(); //2. 切换非阻塞模式 ssChannel.configureBlocking(false); //3. 绑定连接 ssChannel.bind(new InetSocketAddress(9898)); //4. 获取选择器 Selector selector = Selector.open(); //5. 将通道注册到选择器上, 并且指定“监听接收事件” ssChannel.register(selector, SelectionKey.OP_ACCEPT); //6. 轮询式的获取选择器上已经“准备就绪”的事件 while(selector.select() > 0){ //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)” Iterator
it = selector.selectedKeys().iterator(); while(it.hasNext()){ //8. 获取准备“就绪”的是事件 SelectionKey sk = it.next(); //9. 判断具体是什么事件准备就绪 if(sk.isAcceptable()){ //10. 若“接收就绪”,获取客户端连接 SocketChannel sChannel = ssChannel.accept(); //11. 切换非阻塞模式 sChannel.configureBlocking(false); //12. 将该通道注册到选择器上 sChannel.register(selector, SelectionKey.OP_READ); }else if(sk.isReadable()){ //13. 获取当前选择器上“读就绪”状态的通道 SocketChannel sChannel = (SocketChannel) sk.channel(); //14. 读取数据 ByteBuffer buf = ByteBuffer.allocate(1024); int len = 0; while((len = sChannel.read(buf)) > 0 ){ buf.flip(); System.out.println(new String(buf.array(), 0, len)); buf.clear(); } } //15. 取消选择键 SelectionKey it.remove(); } } }}

转载地址:http://yplul.baihongyu.com/

你可能感兴趣的文章
Ubuntu 外网不通解决方案
查看>>
OSChina 周六乱弹 —— 历史总是惊人的相似
查看>>
MySQL 大小写
查看>>
div块上下左右居中
查看>>
eclipse远程debug tomcat
查看>>
CentOs6.5基本环境配置(六):Maven配置
查看>>
Python 创建Django项目
查看>>
JS获取当前项目的根路径
查看>>
操作系统引导区代码
查看>>
程序员有五种错误不应犯
查看>>
无线认证知识点
查看>>
基于python的REST框架eve测试与mongodb的数据操作
查看>>
epoll模型的理解封装与应用
查看>>
Lync 2013部署图片赏析-证书服务安装配置
查看>>
HTML5 本地缓存 (web存储)
查看>>
tomcat redis session共享(包含redis安全设置)
查看>>
iptables中DNAT、SNAT和MASQUERADE的作用
查看>>
kvm命令学习记录
查看>>
小菜鸡进阶之路-First week
查看>>
ORACLE 10g SYSAUX表空间快速增长之WRH$_ACTIVE_SESSION_HISTORY篇
查看>>