当前位置: 首页 > news >正文

阜阳 做网站电商网店

阜阳 做网站,电商网店,金华市建设局网站职称,手机怎么建立自己网站前言:用netty跑了那么久,,也没有真正细枝末节地认识过她,借着2020这年行业大环境,尽一份Coder应有的责任(总结),发现一个蛮优秀的coder有个系列netty一二三,和自己实际项目种用到的差无别二&…

前言:用netty跑了那么久,,也没有真正细枝末节地认识过她,借着2020这年行业大环境,尽一份Coder应有的责任(总结),发现一个蛮优秀的coder有个系列netty一二三,和自己实际项目种用到的差无别二,就转过来(偷个小懒码了),也在必要地方加上了自己的示例图, 这学长内容亲试可关,昵称: 五月的仓颉;原文地址http://www.cnblogs.com/xrq730/p/5260294.html,转载请注明出处

------------------------------------------------------------------------------------------------------------------------

为什么使用Netty

Netty是业界最流行的NIO框架之一,它的健壮性、功能、性能、可定制性、可扩展性在同类框架中都是首屈一指的,它已经得到了成百上千的商用项目的证明。对于为什么使用Netty这个话题,我们先看一下使用原生的NIO有什么缺点:

  • NIO的类库和API繁杂,使用麻烦,需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等,这就像我们会使用Hibernate、MyBatis这些ORM框架而不会直接使用Connection、Statement一样
  • 需要其他额外技能作为铺垫,必须对多线程和网络编程非常熟悉才能写出高质量的NIO程序
  • 可靠性能力补齐,工作量和难度都非常大,例如客户端面临断线重连、网络闪断、半包读写、失败缓存、网络拥塞、异常码流等问题的处理
  • JDK NIO的BUG,例如著名的epoll bug,该问题会导致Selector空轮训,最终导致CPU 100%

也正是因为有种种缺点,因此不建议使用原生的NIO而是建议使用一些比较成熟的NIO框架例如Netty、Mina,这一系列文章讲的是Netty,Netty作为一款高性能NIO框架,其优点总结有:

  • API使用简单、开发门槛低
  • 功能强大,预置了多种编码解码功能,支持多种主流协议
  • 定制能力强,可以通过ChannelHandler对通信框架进行灵活扩展
  • 性能高,与业界其他主流NIO框架对比,Netty性能最优
  • 成熟、稳定,Netty修复了已经发现的所有JDK NIO的BUG,业务开发人员不需要再为NIO的BUG而烦恼
  • 社区活跃、版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会被加入
  • 经历了大规模的商业应用考验,质量得到验证

正因为这些优点,Netty逐渐成为了Java NIO变成的首选框架。

Netty入门Demo

下面演示一下Netty的Demo(注:Demo来自Netty权威指南第三章),本文只写代码与演示结果,不做讲解,对Netty的使用基本讲解放在下一篇文章中,循序渐进,先感性地认识Netty,再理性地认识Netty中的东西。

提一下,本文及之后的文章Netty基于5.0.0.Alpha1这个版本,贴一下我自己的Maven配置(4.0.33.Final)两年开始用的版本,一直没升级过吧:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.xrq.netty</groupId><artifactId>netty-test</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>5.0.0.Alpha1</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.25</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version></dependency></dependencies></project>

首先从服务端代码开始,定义一个TimeServer: 

public class TimeServer {public void bind(int port) throws Exception {// NIO线程组EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler());// 绑定端口,同步等待成功ChannelFuture f = b.bind(port).sync();// 等待服务端监听端口关闭f.channel().closeFuture().sync();} finally {// 优雅退出,释放线程池资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel arg0) throws Exception {arg0.pipeline().addLast(new TimeServerHandler());}}}

TimeServerHandler这么定义:

public class TimeServerHandler extends ChannelHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf)msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "UTF-8");System.out.println("The time server receive order:" + body);String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());ctx.write(resp);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.flush();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}}

 即读取来自客户端的数据,如果是"QUERY TIME ORDER",则把当前时间写到Channel中去。至此,Netty服务端代码已经开发完毕。接下来是Netty客户端代码,首先还是TimeClient:

 

public class TimeClient {public void connect(int port, String host) throws Exception {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {protected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new TimeClientHandler());};});// 发起异步连接操作ChannelFuture f = b.connect(host, port).sync();// 等待客户端连接关闭f.channel().closeFuture().sync();} finally {// 优雅退出,释放NIO线程组group.shutdownGracefully();}}}

 同样的,定义一个TimeClientHandler:

 

public class TimeClientHandler extends ChannelHandlerAdapter {private static final Logger LOGGER = LoggerFactory.getLogger(TimeClientHandler.class);private final ByteBuf firstMessage;public TimeClientHandler() {byte[] req = "QUERY TIME ORDER".getBytes();firstMessage = Unpooled.buffer(req.length);firstMessage.writeBytes(req);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(firstMessage);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf = (ByteBuf)msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "UTF-8");System.out.println("Now is:" + body);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {LOGGER.warn("Unexcepted exception from downstream:" + cause.getMessage());ctx.close();}}

客户端的操作为打印来自服务端的数据,这样,整个Netty Demo代码就写完了,结构比较清楚,都是一个Server+一个Handler的模式,Handler用于处理读取到的信息。

public class CoreTest {@Testpublic void timeServerTest() throws Exception {new TimeServer().bind(8080);}@Testpublic void timeClientTest() throws Exception {new TimeClient().connect(8080, "127.0.0.1");}}

运行Demo

上面写完了Demo,接着写一下测试代码,很简单,分别运行bind方法和connect方法即可:

 

public class CoreTest {@Testpublic void timeServerTest() throws Exception {new TimeServer().bind(8080);}@Testpublic void timeClientTest() throws Exception {new TimeClient().connect(8080, "127.0.0.1");}}

先运行timeServerTest让服务端先启动,再运行timeClientServer让客户端后启动,运行结果服务端的打印为:

The time server receive order:QUERY TIME ORDER

结合代码可以看到,服务端读取到了来自客户端的数据,数据内容为"QUERY TIME ORDER",接着服务端取自己的时间,传输给客户端,看一下客户端的打印:

Now is:Thu Apr 05 21:07:39 CST 2018

打印了来自服务端的时间,这样,利用Netty进行服务端+客户端的相互通信的Demo完成,有了这个Demo,对Netty有了感性上的认识,接着我们一点一点深入去学习Netty。

 ==================================================================================

我不能保证写的每个地方都是对的,每一行代码都经过了认真的推敲、仔细的斟酌。每一篇文章的背后,希望都能看到自己对于技术、对于生活的态度。

我相信乔布斯说的,只有那些疯狂到认为自己可以改变世界的人才能真正地改变世界。面对压力,我可以挑灯夜战、不眠不休;面对困难,我愿意迎难而上、永不退缩。

其实我想说的是,我只是一个程序员,这就是我现在纯粹人生的全部。

更多经历移步博客园:五月的仓颉
==================================================================================

 

另外补充两个自己项目种实际使用到的示例;

1:普通的 tcp-server。

2:基于标准的TLS1.2 双向验证的 tcp-server端启动初始化类

1:普通的 tcp-server:

/* ** Netty 服务端代码* @title SH* @project* @note  普通的tcp-server 启动初始化类* @author alex* @Date 2018/7/5*/
@Component("tcpServer")
public class TcpServer extends Thread {Logger logger = LoggerFactory.getLogger(this.getClass());private final int MAX_LENGTH = 1024;@Autowiredprivate VehMessageHandler vehMessageHandler;/*** netty服务端启动的入口** @author alex*/public void run() {// 配置服务端的NIO线程组EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();/*** 最大连接数量设定 BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,* 用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。*/b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.SO_KEEPALIVE, true)// 通过NoDelay禁用Nagle,使消息立即发出去,不用等待到一定的数据量才发出去.childOption(ChannelOption.TCP_NODELAY, true).childHandler(new ChildChannelHandler());//绑定端口,等待同步成功ChannelFuture f = b.bind(NettyConfig.nettyPort).sync();logger.info("服务监听启用成功,监听端口为:" + NettyConfig.nettyPort);f.channel().closeFuture().sync();} catch (Exception e) {logger.error("启动netty服务失败,请排查原因", e);System.exit(1);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}/* ** 一个完整的业务可能会被TCP拆分成多个包进行发送(拆包),也有可能把多个小的包封装成一个大的数据包发送(粘包),这个就是TCP的拆包和封包问题。*/class ChildChannelHandler extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {ChannelPipeline channelPipeline = channel.pipeline();/*** @Deprecated* 一。解决掉粘包、断包问题(GB23960 未把(0x23,0x23)标识符进行“转义处理”(body中),不能简单采用分隔符处理)。另:evready可以采用* 式1:分隔符,按照guobiao消息中自定义的分隔符“0x23,0x23“,将消息报文分别拆开发送;* 方式2:消息定长,报文大小固定长度,不够空格补全,发送和接收方遵循相同的约定, 这样即使粘包了通过接收方编程实现获取定长报文也能区分。*/
//			byte[] splitByte = new byte[]{0x23,0x23};
//			ByteBuf delimiterStart = Unpooled.copiedBuffer(splitByte);
//			channel.pipeline().addLast("framedecoder",new DelimiterBasedFrameDecoder(MAX_LENGTH, false,
//					delimiterStart));//方式2: 不需要去除分隔符,消息最大只能是1024/*channel.pipeline().addLast( new DelimiterBasedFrameDecoder(1024, false, delimiter));*///这里需要加上把ByteBuf转换为Package对象的handler// channel.pipeline().addLast(new StringDecoder());// readIdle、writeIdle超时忽略,只启用一个AllIdle,这里设置为2min/*** 一。GB23960消息处理:采取根据body中数据数据单元长度截取长度 标识“整包数据”*/channelPipeline.addLast(new StringEncoder(Charset.forName("UTF-8")));channelPipeline.addLast(new GBDelimiterMsgDecoder());channelPipeline.addLast(new IdleStateHandler(0, 0,NettyConfig.timeOut,TimeUnit.SECONDS));
//			channelPipeline.addLast("readTimeOut",new ReadTimeoutHandler(10));channelPipeline.addLast("vehMessageHandler", vehMessageHandler);}}
}

2:基于标准的TLS1.2 双向验证的 tcp-server端

/* ** Netty 服务端代码* @title  SH* @project* @note  基于标准的TLS1.2 双向验证的 tcp-server启动初始化类* @author alex* @Date 2018/7/5*/
@Component("tcpTlsServer")
public class TcpTlsServer extends Thread {Logger logger = LoggerFactory.getLogger(this.getClass());private final int MAX_LENGTH = 1024;@Autowiredprivate VehMessageHandler vehMessageHandler;
//	@Autowired
//	private SocketSSLHandler socketSSLHandler;/*** netty服务端启动的入口** @author alex*/public void run() {// 配置服务端的NIO线程组EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();/*** 最大连接数量设定 BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,* 用于临时存放已完成三次握手的请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。*/b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024).childOption(ChannelOption.SO_KEEPALIVE, true)// 通过NoDelay禁用Nagle,使消息立即发出去,不用等待到一定的数据量才发出去.childOption(ChannelOption.TCP_NODELAY, true).childHandler(new ChildChannelHandler());//绑定端口,等待同步成功ChannelFuture f = b.bind(NettyConfig.nettyPort).sync();logger.info("服务监听启用成功,监听端口为:" + NettyConfig.nettyPort);f.channel().closeFuture().sync();} catch (Exception e) {logger.error("启动netty服务失败,请排查原因", e);System.exit(1);} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}/* ** 一个完整的业务可能会被TCP拆分成多个包进行发送(拆包),也有可能把多个小的包封装成一个大的数据包发送(粘包),这个就是TCP的拆包和封包问题。*/class ChildChannelHandler extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {/*** 解决掉粘包、断包问题* 方式1:分隔符,按照guobiao消息中自定义的分隔符“0x23,0x23“,将消息报文分别拆开发送;* 方式2:消息定长,报文大小固定长度,不够空格补全,发送和接收方遵循相同的约定, 这样即使粘包了通过接收方编程实现获取定长报文也能区分。*/byte[] splitByte = new byte[]{0x23,0x23};ByteBuf delimiterStart = Unpooled.copiedBuffer(splitByte);//			SSLEngine engine = SSLContextFactory.getSSLContext().createSSLEngine();SSLEngine engine = SSLContextFactory.getSslContext().newEngine(channel.alloc());
//			SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();//客户端ca读取jksengine.setUseClientMode(false);engine.setNeedClientAuth(true); //需要客户端认证,默认为falsechannel.pipeline().addLast("ssl",new SslHandler(engine));//不能添加true 否则偶尔出现unknow data未加密(Wireshark 抓包发现)channel.pipeline().addLast(new StringEncoder(Charset.forName("UTF-8")));channel.pipeline().addLast(new GBDelimiterMsgDecoder());/*channel.pipeline().addLast("framedecoder",new DelimiterBasedFrameDecoder(MAX_LENGTH, false,delimiterStart));*///方式2: 不需要去除分隔符,消息最大只能是1024/*channel.pipeline().addLast( new DelimiterBasedFrameDecoder(1024, false, delimiter));*//*** 2: 这里需要加上把ByteBuf转换为Package对象的handler*/// channel.pipeline().addLast(new StringDecoder());// readIdle、writeIdle超时忽略,只启用一个AllIdle,这里设置为2minchannel.pipeline().addLast(new IdleStateHandler(0, 0,NettyConfig.timeOut,TimeUnit.SECONDS));channel.pipeline().addLast("vehMessageHandler", vehMessageHandler);}}
}

 

http://www.lbrq.cn/news/2413585.html

相关文章:

  • 网页微信版官网登录不了百度seo2022
  • 建设项目查询网站搜索引擎都有哪些
  • icp备案网站建设方案书优化关键词首页排行榜
  • 建设银行办信用卡网站首页seo查询优化
  • 动态网站如何维护广州seo网络优化公司
  • 海阳做网站深圳seo优化培训
  • 企业网站建设物美价廉百度百度一下
  • 帝国做网站互联网营销师培训教程
  • 做图素材的网站有哪些互联网营销方案策划
  • 通过apache建设网站宁波网络营销推广咨询报价
  • 做sgs认证公司网站佛山全网营销推广
  • 自己做网站怎么让字体居中nba中国官方网站
  • 长春高铁建站低价刷赞网站推广
  • 网站建设方案功能天津优化公司
  • 网站建设收费标准讯息云南网络推广公司排名
  • 5种有效增加网站流量长沙官网seo服务
  • 郑州网站建设网站推广拓客最有效方案
  • 怎么做虚拟币网站黑龙江最新疫情
  • 做的网站显示不了背景图片信息流优化师简历怎么写
  • 通栏式网站全国最新实时大数据
  • 网站建设公司 温州广告营销
  • 东莞莞城网站建设肇庆seo排名外包
  • 做服装有哪些好的网站有哪些方面苏州疫情最新情况
  • 天涯网站建设路小学线上营销推广公司
  • 简单的asp网站源码东莞软文推广
  • 手机app下载软件英文外链seo兼职
  • 宁波在线制作网站湖北网站seo策划
  • 平板做网站服务器台州seo排名外包
  • 2008 做网站外贸网站推广服务
  • 皖icp阜阳网站建设安徽网站seo公司
  • An End-to-End Attention-Based Approach for Learning on Graphs NC 2025
  • 简洁高效的C++终端日志工具类
  • 30天打牢数模基础-卷积神经网络讲解
  • Kubernetes (K8S)知识详解
  • 嵌入式硬件篇---按键
  • LVS(Linux Virtual Server) 集群