`
longzhun
  • 浏览: 369954 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Netty入门到精通二(转)

 
阅读更多

在第一篇里面我们了解了传统IO,这篇我们就来介绍一下Nio吧,废话就不多说了,来看看代码吧

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.Iterator;

 

/**

 * NIO服务端

 *

 * @author -Jimmy_zjf888-

 */

public class NIOServer {

// 通道管理器

private Selector selector;

 

/**

 * 获得一个ServerSocket通道,并对该通道做一些初始化的工作

 * @param port绑定的端口号

 * @throws IOException

 */

public void initServer(int port) throws IOException {

// 获得一个ServerSocket通道

ServerSocketChannel serverChannel = ServerSocketChannel.open();

// 设置通道为非阻塞

serverChannel.configureBlocking(false);

// 将该通道对应的ServerSocket绑定到port端口

serverChannel.socket().bind(new InetSocketAddress(port));

// 获得一个通道管理器

this.selector = Selector.open();

// 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,

// 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

}

 

/**

 * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理

 *

 * @throws IOException

 */

public void listen() throws IOException {

System.out.println("服务端启动成功!");

// 轮询访问selector

while (true) {

// 当注册的事件到达时,方法返回;否则,该方法会一直阻塞

selector.select();

// 获得selector中选中的项的迭代器,选中的项为注册的事件

Iterator<?> ite = this.selector.selectedKeys().iterator();

while (ite.hasNext()) {

SelectionKey key = (SelectionKey) ite.next();

// 删除已选的key,以防重复处理

ite.remove();

 

handler(key);

}

}

}

 

/**

 * 处理请求

 *

 * @param key

 * @throws IOException

 */

public void handler(SelectionKey key) throws IOException {

 

// 客户端请求连接事件

if (key.isAcceptable()) {

handlerAccept(key);

// 获得了可读的事件

else if (key.isReadable()) {

handelerRead(key);

}

}

 

/**

 * 处理连接请求

 *

 * @param key

 * @throws IOException

 */

public void handlerAccept(SelectionKey key) throws IOException {

ServerSocketChannel server = (ServerSocketChannel) key.channel();

// 获得和客户端连接的通道

SocketChannel channel = server.accept();

// 设置成非阻塞

channel.configureBlocking(false);

 

// 在这里可以给客户端发送信息哦

System.out.println("新的客户端连接");

// 在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。

channel.register(this.selector, SelectionKey.OP_READ);

}

 

/**

 * 处理读的事件

 *

 * @param key

 * @throws IOException

 */

public void handelerRead(SelectionKey key) throws IOException {

// 服务器可读取消息:得到事件发生的Socket通道

SocketChannel channel = (SocketChannel) key.channel();

// 创建读取的缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);

int read = channel.read(buffer);

if(read > 0){

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("服务端收到信息:" + msg);

 

//回写数据

ByteBuffer outBuffer = ByteBuffer.wrap("好的".getBytes());

channel.write(outBuffer);// 将消息回送给客户端

}else{

System.out.println("客户端关闭");

key.cancel();

}

}

 

/**

 * 启动服务端测试

 *

 * @throws IOException

 */

public static void main(String[] args) throws IOException {

NIOServer server = new NIOServer();

server.initServer(8888);

server.listen();

}

 

}

 

 

 

运行上述代码,发现selector.select();这里是一个阻塞点

 

OK,我们看看能否正常运行吧,做程序就是这样,跑一下测试一下,这里我们测试的代码运行一下也不会怎么样,为了学习嘛


 

OK,我们看看能否正常运行吧,做程序就是这样,跑一下测试一下,这里我们测试的代码运行一下也不会怎么样,为了学习嘛

 

学到这里我们总结总结一下吧,传统IO单线程情况下只能有一个客户端,多线程的情况下可以有多个客户端,但非常消耗内存,但NIO就不一样了,他是全能的,一个线程就可以接入多个客户端,为了解释清楚笔者就用如下图片来描述传统IONIO的区别吧

 

如图所示,整个办公室就是我们的系统,ServerSocket就是我们的前台大厅,他监听着端口,

看看有没有客人来,客人我们就理解为socket吧,传统的多线程是不是就是需要多个线程给多个客户端服务啊,要是公司招那么多前台妹子是不是要花一笔不小的开支啊,虽然乐坏了我们这些程序猿了,但对公司来说就是一笔不小的开支,如图所示公司就那么大,人太多都装不下了,连前台妹子都被挤到外面去了( ><) ,那么介绍完传统IO以后,我们来介绍介绍我们的必杀技NIO吧,如图所示。

 

   如上图所示,整个办公室就是我们的系统,ServerSocketChannel就是我们的前台大厅,他监听着端口,看看有没有客人来,客人我们就理解为socket吧,与传统IO不同的是,咱们公司的妹子(线程池)不需要那么多了,这次我们的前台经过特殊培训,她已经不是一般能力的前台妹子了(神马妹子都升级了?能力惊人的逆天),她比较牛能有同时服务多个客人的能力,同时她还可以监听前台大厅,看看有没有新的客人进来,那么她是怎么欢迎新来的可能呢?

//首先我们先让她知道前台大厅在哪

ServerSocketChannel serverChannel = ServerSocketChannel.open();

// 设置通道为非阻塞的,当然也只能设为非阻塞的,设为true会抛异常的

serverChannel.configureBlocking(false);

// 获得一个通道管理器

this.selector = Selector.open();

// 讲大厅交给一个selector,这个selector我们就想象成一个前台妹子吧,SelectionKey我们就理解为一个标记吧

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

通过上述相信你们应该NIO有所了解了吧,是不是比对着电子书看有意思多了,有意思给个赞把,对了笔者讲讲代码中的几个关键点吧,也是在学习过程中发现的,当然如上代码已经进行bug修复

1.当关闭客户端窗口的时候会报错?为什么会报错

答:那是因为客户端关闭的时候我们还在给它写数据,解决方案:

int read = channel.read(buffer);

if(read > 0){

byte[] data = buffer.array();

String msg = new String(data).trim();

System.out.println("服务端收到信息:" + msg);

 

//回写数据

ByteBuffer outBuffer = ByteBuffer.wrap("好的".getBytes());

channel.write(outBuffer);// 将消息回送给客户端

}else{

System.out.println("客户端关闭");

key.cancel();

}

2.我们发现selector.select();这里是一个阻塞点,那么为什么说NIO是非阻塞的?

答:这里我们所说的阻塞并不是select阻塞,而是channel.read(buffer)的时候是否阻塞,而传统IO是会阻塞在那里的,当然我们这里的select可以说是阻塞的,也可以说是非阻塞的,为什么这么说呢?其实select也有其他方法

1).selector.select(timeOut);这里有个带毫秒值的方法,当然这里阻塞timeOut毫秒后会返回,只不过返回0而已

2).selector.wakeup();也可以唤醒selector(官方描述:如果当前的select是阻塞的,用.select()或者select(timeOut),这个方法调用后这些方法都会立马返回结果值),当然在后面讲解Netty源码的时候我会讲解该方法,让大家更好的去理解,这里就不多说了。

3.key.OP_WRITE事件神马时候注册呢?

答:其实真正写的时候很少用,其实WRITE主要描述底层缓存区是否有空间,当然正常的时候缓冲区都是存在足够的空间的,如果存在空间就返回true

分享到:
评论

相关推荐

    netty入门到精通.txt

    根据提供的文件信息“netty入门到精通”,我们可以深入探讨Netty框架的相关知识点,包括其基本概念、核心组件、应用场景以及如何逐步掌握这项技术。 ### Netty框架简介 Netty是一款高性能、异步事件驱动的网络应用...

    Netty入门教程文档

    Netty入门教程文档 Netty是Java的网络编程框架,广泛应用于数据采集服务中,本文将对Netty的基本概念和应用进行详细介绍,并将其与ETL技术结合,讲解如何使用Netty进行数据流转和处理。 1. ETL概述 ETL(Extract...

    netty从入门到精通所有代码

    这个“Netty 从入门到精通所有代码”压缩包包含了一系列的示例代码,帮助开发者逐步理解并掌握 Netty 的核心概念和实际应用。 1. **Netty 基本概念** - **NIO (Non-blocking I/O)**:Netty 是基于 Java NIO 构建的...

    Netty全套学习资源(包括源码、笔记、学习文档等)

    通过阅读源码,我们可以了解到 Netty 如何实现高效的网络通信,例如它的非阻塞 I/O 模型、事件驱动架构、内存池管理以及编码解码器等核心组件。其中,Channel、EventLoop、ByteBuf 等关键类是理解 Netty 的基础,而 ...

    Netty权威指南 PDF电子书下载 带目录书签 完整版

    基础篇 走进Java NIO 入门篇 Netty NIO开发指南 中级篇 Netty编解码开发指南 高级篇 Netty多协议开发和应用 源码分析篇 Netty功能介绍和源码分析 架构和行业应用篇 Netty高级特性

    Netty-In-Action中文版.pdf

    《Netty in Action》是一本深入探讨Netty框架的中文指南,它为读者提供了全面了解和熟练使用Netty所需的知识。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。...

    netty电子书

    Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和...

    Netty权威指南完整版高清pdf

    《Netty权威指南》是一本深入探讨Netty框架的详细教程,旨在帮助读者全面理解并熟练运用Netty进行高性能网络应用开发。Netty是Java领域的一款开源、异步事件驱动的网络应用程序框架,广泛应用于高性能服务器和客户端...

    netty权威指南 PDF电子书下载 带目录书签 完整版

    netty权威指南 PDF电子书下载 带目录书签 完整版,下载

    自己学习netty的笔记和Demo

    2. **Netty入门**:笔记-3和-5探讨了Netty的入门知识,包括如何搭建基本的Netty服务器和客户端,以及如何扩展Netty来处理HTTP服务。这将帮助初学者快速上手,并理解Netty如何处理网络通信。 3. **核心知识**:笔记-...

    Rabbitmq入门到精通.doc

    【RabbitMQ 入门到精通】:RabbitMQ 是一款流行的消息中间件,它基于 AMQP(Advanced Message Queuing Protocol)协议实现,用于在分布式系统中高效地传输消息,从而实现异步处理、解耦和流量控制。本教程旨在帮助...

    Netty权威指南(第2版)

    内容不仅包含Java NIO入门知识、Netty 的基础功能开发指导、编解码框架定制等,还包括私有协议栈定制和开发、Netty 核心类库源码分析,以及Netty 的架构剖析。 《Netty 权威指南(第2 版)》适合架构师、设计师、...

    Netty开发视频教程

    ### Netty开发视频教程知识点详解 #### 一、Netty简介与环境搭建 - **Netty概述**:Netty是一款高性能、异步事件驱动...无论是对于初学者还是有一定基础的开发者来说,这套视频教程都将是入门到精通Netty的最佳选择。

    NettyInAction中文版

    NettyInAction中文版,共13章,从入门到精通。Netty介绍 为什么要使用non-blocking IO(NIO) 阻塞IO(blocking IO)和非阻塞IO(non-blocking IO)对比 Java NIO的问题和在Netty中的解决方案 Netty是基于Java NIO的网络...

    韩顺平循序渐进学java从入门到精通课件笔记

    - **设置布局**:将按钮和面板添加到了窗口的不同位置上。 - **监听器处理**:通过实现`ActionListener`接口并在`actionPerformed()`方法中处理点击事件,实现了背景色的切换。 #### 示例2: MyPanel 类 - **自定义...

    Netty权威指南 第2版 带书签目录

    内容不仅包含Java NIO入门知识、Netty 的基础功能开发指导、编解码框架定制等,还包括私有协议栈定制和开发、Netty 核心类库源码分析,以及Netty 的架构剖析。 《Netty 权威指南(第2 版)》适合架构师、设计师、...

    Netty权威指南 第2版

    8. **最新特性**:第二版可能涵盖了Netty框架的新特性和改进,让读者了解到最新的发展动态。 通过阅读《Netty权威指南 第2版》,开发者不仅可以深入了解Java NIO和Netty框架的工作原理,还能掌握如何有效地利用...

    JAVA学习资源1.0

    1.Java 并发编程从入门到精通 2.并发编程实战 3.算法 4.高效程序员的45个习惯 5.深入java虚拟机 6.阿里巴巴JAVA开发手册 7.Java核心技术 卷1 基础篇 8.Netty_in_Action 9.java性能优化 10.spring源码解析 11.java 8...

Global site tag (gtag.js) - Google Analytics