远方的灯塔 - 专注于服务端技术分享 远方的灯塔 - 专注于服务端技术分享
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)

Terwer Green

一个后端老菜鸟
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)
  • JavaSE

  • 开源框架

  • Linux

  • Struts2

  • Hibernate

  • Webservice

  • 分布式

    • RPC架构设计及IO模型
    • NIO编程及其三大核心原理
    • NIO三大核心之缓冲区(Buffer)
    • NIO三大核心之通道(Channel)
      • NIO三大核心之选择器(Selector)
      • Netty核心原理
      • 线程模型以及传统IO阻塞模型
      • Reactor模型
      • Netty线程模型
      • Netty核心API介绍
      • Netty入门与异步模型
      • Netty高级进阶之Netty编解码器
      • Netty高级进阶之基于Netty的群聊天室案例
      • Netty高级进阶之基于Netty的HTTP服务器开发
      • Netty高级进阶之基于Netty的Websocket开发网页聊天室
      • Netty高级进阶之Netty中的粘包和拆包的解决方案
      • Nety源码剖析
      • 自定义RPC框架之分布式架构网络通信理论
      • 自定义RPC框架之基于Netty实现RPC框架
      • 分布式架构理论
      • 分布式理论之数据一致性
      • 分布式理论之CAP定理
      • 分布式理论之BASE定理
      • 分布式一致性协议之两阶段提交协议(2PC)
      • 分布式一致性协议之三阶段提交协议(3PC)
      • 分布式一致性协议之NWR协议
      • 分布式一致性协议之Gossip协议
      • 分布式一致性协议之Paxos协议
      • 分布式一致性协议之Raft协议
      • 分布式一致性协议之Lease机制
      • 分布式系统设计策略之心跳检测
      • 分布式系统设计策略之高可用
      • 分布式系统设计策略之容错性
      • 分布式系统设计策略之负载均衡
      • 分布式架构服务调用
      • 分布式服务治理之服务协调
      • 分布式服务治理之服务削峰
      • 分布式服务治理之服务降级
      • 分布式服务治理之服务限流
      • 分布式服务治理之服务熔断
      • 分布式服务治理之服务链路追踪
      • 架构设计基本原则之开闭原则(OCP)
      • 架构设计基本原则之单一职责原则(SRP)
      • 架构设计基本原则之接口隔离原则(ISP)
      • 架构设计基本原则之里式替换原则(LSP)
      • 架构设计基本原则之依赖倒置原则(DIP)
      • 架构设计基本原则知识扩展
      • 分布式架构知识拓展与总结
    • 分布式框架

    • 后端开发
    • 分布式
    terwer
    2022-05-04
    目录

    NIO三大核心之通道(Channel)

    # 通道(Channel)

    # 基本介绍

    NIO中所有的IO都是从通道(Channel)开始的。NIO的通道类似于流,但是有区别:

    1. 通道可读可写,流一般是单向的(只能读或者写,所以之前socket的demo里面分别创建一个输入流和输出流)。

    2. 通道可以异步读写。

    3. 通道总是基于缓冲区Buffer来读写

      image-20220418214447367

    # Channel的常用类介绍

    1. Channel接口

      常用的Channel实现类有:FileChannel、DatagramChannel、ServerSocketChannel和SocketChannel

      FileChannel用于文件的数据读写,DatagramChannel用于UDP数据的读写,ServerSocketChannel和SocketChannel用于TCP数据的读写。

      ServerSocketChannel类似于ServerSocket,SocketChannel类似于Socket。

      classDiagram
      direction BT
      class Channel {
      <<Interface>>
      
      }
      class DatagramChannel
      class FileChannel
      class ServerSocketChannel
      class SocketChannel
      
      DatagramChannel  ..>  Channel 
      FileChannel  ..>  Channel 
      ServerSocketChannel  ..>  Channel 
      SocketChannel  ..>  Channel 
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15

      如果无法显示图片,请看这里

      image-20220418215316887

    2. SocketChannel和ServerSocketChannel

      类似于Socket和ServerSocket,可用于客户端与服务器的通信。

    # ServerSocketChannel

    服务端实现步骤:

    1. 打开一个服务端通道
    2. 绑定对应的端口号
    3. 通道默认是阻塞的,需要设置为非阻塞
    4. 检查是否有客户端连接,有客户端连接会返回对应的通道
    5. 获取客户端传递过来的数据,并把数据放在byteBuffer这个缓冲区中
    6. 给客户端回写数据
    7. 释放资源
    /**
     * 服务端
     *
     * @name: NIOServer
     * @author: terwer
     * @date: 2022-04-18 21:59
     **/
    public class NIOServer {
        public static void main(String[] args) throws IOException, InterruptedException {
            // 1. 打开一个服务端通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 2. 绑定对应的端口号
            serverSocketChannel.bind(new InetSocketAddress(9999));
            // 3. 通道默认是阻塞的,需要设置为非阻塞
            // true为阻塞,false为非阻塞
            serverSocketChannel.configureBlocking(false);
            System.out.println("服务端启动成功=========");
    
            while (true) {
                // 4. 检查是否有客户端连接,有客户端连接会返回对应的通道
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel == null) {
                    System.out.println("没有客户端连接,做别的事情");
                    Thread.sleep(2000);
                    continue;
                }
    
                // 5. 获取客户端传递过来的数据,并把数据放在byteBuffer这个缓冲区中
                ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                // 正数,读到的字节
                // 0,没有读到数据
                // -1,读到了文件末尾
                int read = socketChannel.read(byteBuffer);
                System.out.println("客户端发来的消息:" + new String(byteBuffer.array(), 0, read));
    
                // 6. 给客户端回写数据
                socketChannel.write(ByteBuffer.wrap("你好,我是服务端".getBytes(StandardCharsets.UTF_8)));
    
                // 7. 释放资源
                socketChannel.close();
            }
    
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44

    # SocketChannel

    客户端实现步骤:

    1. 打开通道
    2. 设置连接IP和端口号
    3. 写出数据
    4. 读取服务器写回的数据
    /**
     * 客户端
     *
     * @name: NIOClient
     * @author: terwer
     * @date: 2022-04-18 22:11
     **/
    public class NIOClient {
        public static void main(String[] args) throws IOException {
            // 1. 打开通道
            SocketChannel socketChannel = SocketChannel.open();
            // 2. 设置连接IP和端口号
            socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999));
            // 3. 写出数据
            socketChannel.write(ByteBuffer.wrap("你好,我是客户端".getBytes(StandardCharsets.UTF_8)));
            // 4. 读取服务器写回的数据
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int read = socketChannel.read(byteBuffer);
            System.out.println("服务端回话:" + new String(byteBuffer.array(), 0, read));
            // 5.释放资源
            socketChannel.close();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    运行效果

    image-20220418221859423

    image-20220418221828926

    编辑 (opens new window)
    #nio#channel
    上次更新: 2023/02/22, 13:47:25
    NIO三大核心之缓冲区(Buffer)
    NIO三大核心之选择器(Selector)

    ← NIO三大核心之缓冲区(Buffer) NIO三大核心之选择器(Selector)→

    最近更新
    01
    解决css部分border被圆角切掉之后圆角的边框消失问题
    03-18
    02
    使用TypeScript开发一个自定义的Node-js前端开发脚手架
    03-08
    03
    Github-Actions使用release-please实现自动发版
    03-06
    更多文章>
    Theme by Vdoing | Copyright © 2011-2023 Terwer Green | MIT License | 粤ICP备2022020721号-1 | 百度统计
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式