Java NIO SocketChannel简述及示例

本文介绍了Java NIO中的SocketChannel,它提供了一种非阻塞的I/O模型,提高了高并发场景下的性能。通过SocketChannel,服务器可以单线程轮询处理多个客户端连接,减少了线程切换开销。文中还包含工作原理、代码示例和涉及的知识扩充,如Channel、Buffer和Selector等。
摘要由CSDN通过智能技术生成

JAVA NIO之SocketChannel

1. 简述

NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道

2. 特点

1. 非阻塞
2. 单线程
3. 轮循

3. 解决问题

当我们使用socket进行通信时, 建立后的链接需保持通信状态则不可关闭, 会启动分线程进行并发通信, 其中大部分时间会是阻塞状态,等待接收消息, 会造成大量的线程阻塞, 对于cpu需要维护线程之间的切换和调用, 在高并发是性能非常低, 因此使用nio可有效的提高效率

4. demo功能

客户端每隔2秒发送一次数据到服务器端, 服务器在其消息前加hello并回复客户端信息

  1. server端使用非阻塞模式单线程轮循的方式进行与client端通信处理
  2. client端使用2个线程进行运作, 一个线程用于定时发送消息到server端, 另一个线程用于读取server端消息

5. 工作原理

1. client注册SocketChannel到server中
在这里插入图片描述
第一步: 创建ServerSocketChannel服务器端并绑定通信端口8000, 存入selector挑选器keys中, 并注册accept事件
第二步: 客户端链接服务器的8000端口, 与服务器端进行通信,触发服务器端的accept事件
第三步: 挑选器挑选出本次需要执行的keys (ServerSocketChannel)存入挑选结果及selectedKeys中, 等待执行
第四步: 执行ServerSockerChannel.accept处理方式, 即获取与客户端client1通信的SocketChannel对象, 并未其注册read事件, 存储到挑选器中
第五步: 执行完本次挑选的结果集后, 清空selectedKeys集合即可
后续客户端连接服务器便重复第二,三,四步即可

2. client与server端的通信
在这里插入图片描述
第一步: client1和client3发送消息到server, 触发服务器端的read事件
第二步: 挑选器挑选出本次需要执行的keys (ServerSocketChannel)存入挑选结果及selectedKeys中, 等待执行
第三步: 遍历筛选出来的client1和client2的链接, 分别读取数据, 并返回响应消息写入到SocketChannel中
第四步: client通过SocketChannel接收server端发送的消息, 进行处理
重复以上步骤即可完成server和client端的通信

3. 特点
在server端, 使用selector的select方法进行轮循挑选触发事件的链接, 使用单线程即可完成与客户端的通信过程, 极大的提高了服务器端的性能, 在高并发时非常实用

6. 代码示例

1. ServerChannel

package pro.nio.socket;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * nio之socket通信服务器端
 */
public class ServerChannel {
   
    public static void main(String[] args) throws IOException {
   
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        // 开启挑选器
        Selector selector = Selector.open();
        // 开启ServerSocketChannel通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress("localhost", 8000));
            // 设置非阻塞模式
        serverSocketChannel.configureBlocking(false);
            // 在挑选器中注册通道(服务器通道)
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值