Netty是建立在NIO基础之上,Netty在NIO之上又提供了更高层次的抽象。

在Netty里面,Accept连接可以使用单独的线程池去处理,读写操作又是另外的线程池来处理。

Accept连接和读写操作也可以使用同一个线程池来进行处理。而请求处理逻辑既可以使用单独的线程池进行处理,也可以跟放在读写线程一块处理。线程池中的每一个线程都是NIO线程。用户可以根据实际情况进行组装,构造出满足系统需求的并发模型。

Netty提供了内置的常用编解码器,包括行编解码器[一行一个请求],前缀长度编解码器[前N个字节定义请求的字节长度],可重放解码器[记录半包消息的状态],HTTP编解码器,WebSocket消息编解码器等等

Netty提供了一些列生命周期回调接口,当一个完整的请求到达时,当一个连接关闭时,当一个连接建立时,用户都会收到回调事件,然后进行逻辑处理。

Netty可以同时管理多个端口,可以使用NIO客户端模型,这些对于RPC服务是很有必要的。

Netty除了可以处理TCP Socket之外,还可以处理UDP Socket。

在消息读写过程中,需要大量使用ByteBuffer,Netty对ByteBuffer在性能和使用的便捷性上都进行了优化和抽象。

服务端:

package com.kenson.netty.server;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;public class NettyServer {/*** 端口*/private int port;public NettyServer(int port) {this.port = port;}public void run() {//EventLoopGroup是用来处理IO操作的多线程事件循环器//负责接收客户端连接线程EventLoopGroup bossGroup = new NioEventLoopGroup();//负责处理客户端i/o事件、task任务、监听任务组EventLoopGroup workerGroup = new NioEventLoopGroup();//启动 NIO 服务的辅助启动类ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup);//配置 Channelbootstrap.channel(NioServerSocketChannel.class);bootstrap.childHandler(new ServerIniterHandler());//BACKLOG用于构造服务端套接字ServerSocket对象,// 标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最大长度bootstrap.option(ChannelOption.SO_BACKLOG, 1024);//是否启用心跳保活机制bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);try {//绑定服务端口监听Channel channel = bootstrap.bind(port).sync().channel();System.out.println("server run in port " + port);//服务器关闭监听/*channel.closeFuture().sync()实际是如何工作:channel.closeFuture()不做任何操作,只是简单的返回channel对象中的closeFuture对象,对于每个Channel对象,都会有唯一的一个CloseFuture,用来表示关闭的Future,所有执行channel.closeFuture().sync()就是执行的CloseFuturn的sync方法,从上面的解释可以知道,这步是会将当前线程阻塞在CloseFuture上*/channel.closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();} finally {//关闭事件流组
            bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}public static void main(String[] args) {new NettyServer(8899).run();}
}

服务端业务逻辑处理:

package com.kenson.netty.server;import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;public class ServerHandler extends SimpleChannelInboundHandler<String> {/*** 所有的活动用户*/public static final ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);/*** 读取消息通道** @param context* @param s* @throws Exception*/@Overrideprotected void channelRead0(ChannelHandlerContext context, String s)throws Exception {Channel channel = context.channel();//当有用户发送消息的时候,对其他的用户发送消息for (Channel ch : group) {if (ch == channel) {ch.writeAndFlush("[you]: " + s + "\n");} else {ch.writeAndFlush("[" + channel.remoteAddress() + "]: " + s + "\n");}}System.out.println("[" + channel.remoteAddress() + "]: " + s + "\n");}/*** 处理新加的消息通道** @param ctx* @throws Exception*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();for (Channel ch : group) {if (ch == channel) {ch.writeAndFlush("[" + channel.remoteAddress() + "] coming");}}group.add(channel);}/*** 处理退出消息通道** @param ctx* @throws Exception*/@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();for (Channel ch : group) {if (ch == channel) {ch.writeAndFlush("[" + channel.remoteAddress() + "] leaving");}}group.remove(channel);}/*** 在建立连接时发送消息** @param ctx* @throws Exception*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();boolean active = channel.isActive();if (active) {System.out.println("[" + channel.remoteAddress() + "] is online");} else {System.out.println("[" + channel.remoteAddress() + "] is offline");}ctx.writeAndFlush("[server]: welcome");}/*** 退出时发送消息** @param ctx* @throws Exception*/@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();if (!channel.isActive()) {System.out.println("[" + channel.remoteAddress() + "] is offline");} else {System.out.println("[" + channel.remoteAddress() + "] is online");}}/*** 异常捕获** @param ctx* @param e* @throws Exception*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable e) throws Exception {Channel channel = ctx.channel();System.out.println("[" + channel.remoteAddress() + "] leave the room");ctx.close().sync();}}

服务端处理器注册:

package com.kenson.netty.server;import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class ServerIniterHandler extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//管道注册handlerChannelPipeline pipeline = socketChannel.pipeline();//编码通道处理pipeline.addLast("decode", new StringDecoder());//转码通道处理pipeline.addLast("encode", new StringEncoder());//聊天服务通道处理pipeline.addLast("chat", new ServerHandler());}
}

客户端:

package com.kenson.netty.client;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.apache.commons.lang3.StringUtils;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class NettyClient {private String ip;private int port;private boolean stop = false;public NettyClient(String ip, int port) {this.ip = ip;this.port = port;}public void run() throws IOException {//设置一个多线程循环器EventLoopGroup workerGroup = new NioEventLoopGroup();//启动附注类Bootstrap bootstrap = new Bootstrap();bootstrap.group(workerGroup);//指定所使用的NIO传输channelbootstrap.channel(NioSocketChannel.class);//指定客户端初始化处理bootstrap.handler(new ClientIniterHandler());try {//连接服务Channel channel = bootstrap.connect(ip, port).sync().channel();while (true) {//向服务端发送内容BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));String content = reader.readLine();if (StringUtils.isNotEmpty(content)) {if (StringUtils.equalsIgnoreCase(content, "q")) {System.exit(1);}channel.writeAndFlush(content);}}} catch (InterruptedException e) {e.printStackTrace();System.exit(1);} finally {workerGroup.shutdownGracefully();}}public static void main(String[] args) throws Exception {new NettyClient("127.0.0.1", 8899).run();}
}

客户端逻辑处理:

package com.kenson.netty.client;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;public class ClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {//打印服务端的发送数据
        System.out.println(s);}
}

客户端处理器注册:

package com.kenson.netty.client;import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class ClientIniterHandler extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//注册管道ChannelPipeline pipeline = socketChannel.pipeline();pipeline.addLast("decoder", new StringDecoder());pipeline.addLast("encoder", new StringEncoder());pipeline.addLast("http", new HttpClientCodec());pipeline.addLast("chat", new ClientHandler());}
}

测试时先启动服务端,再启动客户端。。。

声明: 本文借鉴网络资源,来自:https://www.cnblogs.com/kingsonfu/p/8635064.html

如果侵犯您的利益, 请联系本人删除

转载于:https://www.cnblogs.com/Mr-Kenson/p/9700116.html

Netty 的基本简单实例【服务端-客户端通信】相关推荐

  1. socket编程 -- epoll模型服务端/客户端通信的实现

    https://blog.csdn.net/y396397735/article/details/50680359 本例实现如下功能: 支持多客户端与一个服务端进行通信,客户端给服务端发送字符串数据, ...

  2. java nio 客户端_Java网络编程:Netty框架学习(二)---Java NIO,实现简单的服务端客户端消息传输...

    概述 上篇中已经讲到Java中的NIO类库,Java中也称New IO,类库的目标就是要让Java支持非阻塞IO,基于这个原因,更多的人喜欢称Java NIO为非阻塞IO(Non-Block IO), ...

  3. netty源码学习之服务端客户端初始化

    文章目录 1. AbstractBootstrap类简介 1.1. 核心方法 2. netty服务端创建 2.1. 服务端启动入口 2.2. doBind()方法 2.3. netty服务初始化 2. ...

  4. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答...

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  5. Java网络编程(一)- 一个简单的服务端/客户端应用程序

    在Java中,我们使用java.net.Socket及其相关类来完成有关网络的相关功能.Socket类非常简单易用,因为Java技术隐藏了建立网络连接和通过连接发送数据的复杂过程.下面所说的内容只适用 ...

  6. Go实现简单的TCP服务端客户端通信(有黏包)

    目录 客户端代码 服务端代码 封包协议 客户端代码 // socket_stick/client2/main.gofunc main() {conn, err := net.Dial("tc ...

  7. 连接主机Java网络编程(一)- 一个简单的服务端/客户端应用程序

    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,迎欢批评指正 在Java中,我们应用java.net.Socket及其关相类来成完有关络网的关相功能.Socket类非常简略易用,因为Java术技 ...

  8. netty java_GitHub - leihuazhe/Java11-Netty-Demo: 基于Java11 构建的 netty 服务端客户端 模块化例子...

    Java11-Netty-Demo Java11 基于maven构建的简单的服务端客户端分离模块调用的例子 Java 11 从 Java9 开始引入了模块化的概念.使用Java11 也需要以模块化的方 ...

  9. 【初识Netty使用Netty实现简单的客户端与服务端的通信操作Netty框架中一些重要的类以及方法的解析】

    一.Netty是什么? Netty 由 Trustin Lee(韩国,Line 公司)2004 年开发 本质:网络应用程序框架 实现:异步.事件驱动 特性:高性能.可维护.快速开发 用途:开发服务器和 ...

最新文章

  1. 【HTML】记录自己丢人过程:文本换行缩进都不会
  2. linkedlist java 实现_Java LinkedList 实现原理
  3. 二分搜索 HDOJ 2289 Cup
  4. KindEditor在eclipse里的配置方法
  5. 物联网大数据平台软件开发架构案例解析
  6. [[UIScreen mainScreen] bounds] 返回的屏幕尺寸不对
  7. sqlite具体操作篇
  8. spring mvc 返回json的配置
  9. Mac系统添加MySQL配置文件
  10. 联想笔记本计算机在哪里找不到,Win10 Lenovo笔记本电脑显示找不到相机
  11. 如何通过一根网线连接两台电脑,实现数据的传输?
  12. 最新PHP对接微信支付,发起商家转账API,商家转账到零钱
  13. 【计算机毕业设计】123网上商城系统设计与实现
  14. 4、51单片机——LCD1602 驱动(郭天祥)
  15. 记一个脚本解释器的开发
  16. 【折半搜索-经典题目】中山纪念中学暑期游Day13——【GDOI2017模拟8.15】Buy
  17. gta5维护服务器,GTA6再等10年?R星强行续命GTA5,下月更新地图挤爆服务器
  18. 设置控件评分星星控件
  19. 联想笔记本电脑开机后一直黑屏的解决办法
  20. 异或差分序列_差分序列的性质及应用

热门文章

  1. php框架中数据库模型层原理,简单模拟ThinkPHP框架模型层对数据库的链式操作-Go语言中文社区...
  2. 自学前端真的没有前途吗?
  3. 老生常谈的一个问题,转行学习编程,是自学还是报班
  4. 6 个快速学会 JavaScript 的秘诀!
  5. python中线程同步_Python线程同步在实际应用中功能体现
  6. android项目中有哪几种依赖关系,Android Studio项目中三种依赖的添加方式
  7. python 制作简单网站_新手小白 做python爬虫 爬什么网站比较简单?
  8. html根据菜单角色配置菜单代码,CSS设置列表样式和创建导航菜单实现代码
  9. 易语言html到画板,易语言画板使用方法图解
  10. linux arm交叉编译ko,Ubuntu嵌入式交叉编译环境arm-linux-gcc