java的netty框架,使用netty的开源框架

  java的netty框架,使用netty的开源框架

  00-1010什么是NettyIO模型BIOBIO编程简单进程BIO简单实例NIOBufferBuffer基本上使用了缓冲通道的四个主要属性本地文件写案例本地文件读案例本地文件复制案例选择器

  00-1010异步、事件驱动的网络应用框架,用于快速开发高性能、高可靠性的网络IO程序。它主要针对TCP协议下面向客户的高并发应用。它本质上是一个NIO框架,适用于服务器通信等场景。异步:发送一个请求而不等待响应,然后程序停止运行。

  事件驱动:连接事件或断开事件、读事件或写事件的后续处理。

  Netty的典型应用:

  高性能rpc框架用于调用远程服务(过程),如Dubbo。游戏行业,页面数据交互。大数据领域,如Hadoop高性能通信和序列化组件(AVRO)。

  00-1010简单理解就是用什么通道发送和接收数据。

  BIO:一次连接一个线程,什么都不做就连接会造成不必要的线程开销。它适用于连接数少且固定的体系结构。

  NIO:服务器有一个线程(或多个线程)并维护一个多路复用器。多路复用器处理IO线程。它适用于具有大量连接和短连接的体系结构。

  AIO:是异步的,非阻塞的,但是还没有得到广泛的应用。适用于连接多、连接长的架构。

  

目录

 

  00-1010服务器创建并启动服务器套接字。客户端启动套接字与服务器通信。默认情况下,服务器将为每个客户端创建一个线程。客户端发送请求后,首先询问线程是否有响应,如果没有,则等待或拒绝。如果有响应,请等待请求结束后再继续。(阻塞)

  00-1010 public class bioserver { public static void main(string[]args)throwsioexception {//为了方便起见,直接用executors创建了线程池Executorservice=executors . new cached thread pool();//指定服务器端口server socket server socket=new server socket(6666);System.out.println(服务器启动);While(true){ //阻塞等待连接Socket Socket=server Socket . accept();System.out.println(“连接到客户端”);//每个连接对应一个线程service . execute(newrunnable(){ @ override public void run(){ try { handler(socket));} catch(Exception e){ e . printstacktrace();} } });} }公共静态void处理程序(Socket socket)抛出io exception { system . out . println( thread : thread . current thread()。getId());byte[] bytes=新字节[1024];InputStream InputStream=socket . getinputstream();While (true){ //Block等待读取int n=inputstream . read(bytes);如果(n!=-1){ system . out . println(new String(bytes,0,n));} else { break

   } } socket.close(); }}测试:使用windows的telnet

  

 

  使用 ctrl+]

  

 

  

 

   可以在服务端控制台看到,已经读取到发送的数据

  

 

  

 

  

NIO

三大核心部分:Channel(可类比Socket),Buffer,Selector

 

  大概是这个样子。客户端和Buffer交互,Buffer和Channel是一对一的关系。Selector选择操作Channel(事件驱动,如果Channel有事件发生,Selector才去选择操作。)

  

 

  

 

  

Buffer

 

  

Buffer基本使用

ByteBuffer使用场景较为广泛。

 

  buffer就是一个内存块,所以说nio是面向块/缓冲,底层是数组。数据读写是通过buffer。可以使用方法flip切换读写。

  

public class BufferNio { public static void main(String[] args) { //创建buffer容量为5个int IntBuffer buffer = IntBuffer.allocate(5); //放数据 buffer.put(1); buffer.put(2); buffer.put(3); buffer.put(4); buffer.put(5); //读写切换 buffer.flip(); //取数据 //内部维护一个索引,每次get索引都会往后边移动 while(buffer.hasRemaining()){ System.out.println(buffer.get()); } }}

 

  

Buffer四个主要属性

 // Invariants: mark <= position <= limit <= capacity private int mark = -1; private int position = 0; private int limit; private int capacity;

mark:标记,很少改变

 

  position:下一个要被读元素的位置,为下次读写做准备

  limit:缓冲器当前的终点,不能对缓冲区极限意外的区域读写,可变。

  capacity:不可变,创建时指定的最大容量。

  上边出现了读写切换的方法flip,我们看下源码,可以看出来通过改变属性实现可读可写的。

  

 public final Buffer flip() { limit = position; position = 0; mark = -1; return this; }

可以通过啊更改limit或者position来实现你想要的操作。参数自己决定

 

  

 buffer.limit(2); buffer.position(1);

 

  

Channel

可读可写,上接Selector,下连Buffer。

 

  当客户端连接ServerSocketChannel时,创建客户端自己的SocketChannel。

  

 

  

本地文件写案例

public class ChannelNio { public static void main(String[] args) throws IOException { String str = "少壮不努力,老大徒伤悲"; //创建输出流 FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); //获取FileChannel FileChannel channel = os.getChannel(); //创建缓冲 ByteBuffer buffer = ByteBuffer.allocate(1024); //把字符串放入缓冲区 buffer.put(str.getBytes()); //反转ByteBuffer buffer.flip(); //将ByteBuffer写入到FileChannel channel.write(buffer); //关闭流 os.close(); }}

图示理解

 

  

 

  

 

  

本地文件读案例

public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); FileChannel channel = is.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer); System.out.println(new String(buffer.array())); is.close(); }}

 

  

本地文件拷贝案例

方法一

 

  

public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\a.txt"); FileChannel channel = is.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\b.txt"); FileChannel osChannel = os.getChannel(); while (true){ buffer.clear(); int i = channel.read(buffer); if(i==-1){ break; } buffer.flip(); osChannel.write(buffer); } is.close(); os.close(); }}

方法二

 

  

public class ChannelNio { public static void main(String[] args) throws IOException { FileInputStream is = new FileInputStream("D:\xxxxxxxxxxxxxxxxxxx\HELP.md"); FileChannel channel = is.getChannel(); FileOutputStream os = new FileOutputStream("D:\xxxxxxxxxxxxxxxxxxx\HELP222.md"); FileChannel osChannel = os.getChannel(); osChannel.transferFrom(channel,0,channel.size()); is.close(); os.close(); }}

 

  

Selector

用一个线程处理多个客户端连接。可以检测多个注册通道的事件,并作出相应处理。不用维护所有线程。

 

  

 

  Selector可以获得被注册的SocketChannel的一个SelectionKey集合,然后监听select,获得有事件发生的SelectionKey,最后通过SelectionKey获得通道进行相应操作,完成业务。

  到此这篇关于Java笔记之从IO模型到Netty框架学习初识篇的文章就介绍到这了,更多相关Java Netty框架内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: