Netty是由JBOSS提供的一个java开源框架。Netty提供异步的事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

    Netty基于java的NIO核心:缓存区、通道、选择器这里推荐一本书:java NIO,出版社是O'REILLY。

  一、缓存区。

    缓冲区的工作与通道紧密联系,通道是I/O传输发生时通过的入口,而缓冲区是这些数据传输的来源或目标。对于离开缓冲区的传输,你想传递出去的数据被置于一个缓冲区,被传送到通道。对于传回缓冲区的传输,一个通道将数据放置在你所提供的缓冲区中。这种在协同对象之间进行的缓冲区数据传递是高效数据处理的关键。

    缓冲区的属性:容量(capacity能够容纳的数据元素的最大数量)、上界(limit现存元素的计数)、标记(mark一个备忘位置)、位置(Posistion下一个要被读或写的元素的索引),还有缓冲区操作:翻转、压缩等。

    这里只简介那个位置指针就好了,一切从它开始。

    初始状态:一个空的字节缓冲区,position指向0

        Netty 学习笔记

    接着我们写入一些数据,例如:

    byteBuffer.put(110);

    byteBuffer.put(120);

    现在的状态是:posistion指向2了,如果再写入数据,那么就会在posistion(这里是2)的位置继续向上存储了。如果你把指针设置为1,那么数据就会从1位置开始写入,原先的数据会被覆盖

      Netty 学习笔记

    如果你需要把数据读出来,那么你需要把指针重置0,然后调用get()方法获取第一个字节,这时候posistion会自动+1,指向1,如此类推直到把全部数据读完。

    示例:

      

 1 public static void main(String[] args) {
 2         ByteBuffer buffer = ByteBuffer.allocate(10);
 3         buffer.put((byte) 110);//posistion->1
 4         buffer.put((byte) 120);//posistion->2
 5         
 6         //获取posistion为2的数据,即缓存区第三个元素。
 7         System.out.println("byteBuffer get:"+buffer.get());
 8         //翻转,使posistion指向0
 9         buffer.flip();
10         
11         //获取posistion为0的数据,即缓存区第一个个元素。此时posistion指向1
12         System.out.println("byteBuffer get:"+buffer.get());
13         //获取posistion为1的数据,即缓存区第二个个元素。此时posistion指向2
14         System.out.println("byteBuffer get:"+buffer.get());
15         
16         //或者可以直接指定下标
17         System.out.println("byteBuffer get(0):"+buffer.get(0));
18         System.out.println("byteBuffer get(1):"+buffer.get(1));
19         
20     }

    输出结果:    

        byteBuffer get:0
        byteBuffer get:110
        byteBuffer get:120
        byteBuffer get(0):110
        byteBuffer get(1):120

 

 

   二、通道。

    Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据。通道是一种途径,借助该途径,可以用最小的总开销来访问操作系统本身的I/O服务。缓冲区则是通道内部用来发送和接受数据的端点。

    我们在网络编程中主要用到四个通道:文件通道FileChannel、套接字通道ServerSocketChannel/SocketChannel/DatagramChannel。其中FileChannel和DatagramChannel不在讨论范围。

    要想使用ServerSocketChannel和SocketChannel,首先要打开通道,然后绑定端口,连接成功后就可以对Buffer进行读和写的操作了(记住,ServerSocket/Socket是通过inputStream和outputStream对数据进行操作的,而通道的操作对象是缓冲区):

    

 1 public static void main(String[] args) {
 2         int serverPort = 8001;
 3         ServerSocketChannel serverChannel;
 4         try {
 5             //打开通道
 6             serverChannel = ServerSocketChannel.open();
 7             //ServerSocketChannel本身不提供绑定功能,只能调用它所包装的ServerSocket的方法
 8             serverChannel.socket().bind(new InetSocketAddress(serverPort));
 9         } catch (IOException e) {
10         }
11         
12         try {
13             SocketChannel clientChannel = SocketChannel.open();
14             clientChannel.connect(new InetSocketAddress("192.168.21.94",serverPort));
15         } catch (IOException e) {
16         }
17         
18     }

  他们继承了WritableByteChannel和ReadableByteChannel接口,从而有了读和写的可能:

    

1 public interface WritableByteChannel{
2     public int write(ByteBuffer src) throws IOException;
3 }
4 
5 public interface ReadableByteChannel{
6     public int read(ByteBuffer dst) throws IOException;           
7 }

  下面展示一个简单的示例:

  

 1 public class ServerChannelTest {
 2 
 3     public static void main(String[] args) {
 4         int serverPort = 8001;
 5         ServerSocketChannel serverChannel;
 6         try {
 7             //打开通道
 8             serverChannel = ServerSocketChannel.open();
 9             //ServerSocketChannel本身不提供绑定功能,只能调用它所包装的ServerSocket的方法
10             serverChannel.socket().bind(new InetSocketAddress(serverPort));
11             System.out.println("wait from client……");
12             SocketChannel accept = serverChannel.accept();
13             ByteBuffer buffer = ByteBuffer.allocate(10);
14             accept.read(buffer);
15             buffer.flip();
16             System.out.println("rec from client:"+buffer.get());
17         } catch (IOException e) {
18             e.printStackTrace();
19         }
20     }
21 
22 }
23 
24 
25 
26 public class ClientChannelTest {
27 
28     public static void main(String[] args) {
29         int serverPort = 8001;
30         try {
31             SocketChannel clientChannel = SocketChannel.open();
32             clientChannel.connect(new InetSocketAddress("127.0.0.1",serverPort));
33             ByteBuffer buffer = ByteBuffer.allocate(10);
34             buffer.put((byte) 1);
35             buffer.flip();
36             clientChannel.write(buffer);
37         } catch (IOException e) {
38             e.printStackTrace();
39         }
40         
41     }
42 
43 }
View Code

相关文章:

  • 2021-11-30
  • 2021-06-30
  • 2021-05-01
  • 2021-08-15
  • 2021-11-01
猜你喜欢
  • 2021-05-15
  • 2022-01-30
相关资源
相似解决方案