Netty+SpringBoot+FastDFS+Html5实现聊天App详解(一)
Netty学习
Netty+SpringBoot+FastDFS+Html5实现聊天App,项目介绍:https://segmentfault.com/a/11...
Netty+SpringBoot+FastDFS+Html5实现聊天App,项目github链接:https://github.com/ShimmerPig...
本章练习完整代码链接:https://github.com/ShimmerPig...
IO编程与NIO编程
传统IO编程性能分析
1.线程资源受限:线程是操作系统中非常宝贵的资源,同一时刻有大量的线程处于阻塞状态是非常严重的资源浪费,操作系统耗不起。
2.线程切换效率低下:单机cpu核数固定,线程爆炸之后操作系统频繁进行线程切换,应用性能急剧下降。
3.除了以上两个问题,IO编程中,我们看到数据读写是以字节流为单位,效率不高。
为了解决这三个问题,JDK在1.4之后提出了NIO。下面简单描述一下NIO是如何解决以上三个问题的。
线程资源受限
线程切换效率低下
由于NIO模型中线程数量大大降低,线程切换效率因此也大幅度提高。
IO读写以字节为单位
NIO解决这个问题的方式是数据读写不再以字节为单位,而是以字节块为单位。IO模型中,每次都是从操作系统底层一个字节一个字节地读取数据,而NIO维护一个缓冲区,每次可以从这个缓冲区里面读取一块的数据。
hello netty
完整代码链接:https://github.com/ShimmerPig...
//主线程
EventLoopGroup bossGroup = new NioEventLoopGroup();
//从线程
EventLoopGroup workerGroup = new NioEventLoopGroup();
定义服务端的启动类serverBootstrap,需要设置主从线程,NIO的双向通道,与子处理器(用于处理workerGroup),这里的子处理器后面我们会手动创建。
// netty服务器的创建, ServerBootstrap 是一个启动类ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup) // 设置主从线程组.channel(NioServerSocketChannel.class) // 设置nio的双向通道.childHandler(new HelloServerInitializer()); // 子处理器,用于处理workerGroup
启动服务端,绑定8088端口,同时设置启动的方式为同步的,这样我们的Netty就会一直等待,直到该端口启动完毕。
ChannelFuture channelFuture = serverBootstrap.bind(8088).sync();
channelFuture.channel().closeFuture().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("HttpServerCodec", new HttpServerCodec());
pipeline.addLast("customHandler", new CustomHandler());
if (msg instanceof HttpRequest) {// 显示客户端的远程地址System.out.println(channel.remoteAddress());// 定义发送的数据消息ByteBuf content = Unpooled.copiedBuffer("Hello netty~", CharsetUtil.UTF_8);// 构建一个http responseFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);// 为响应增加数据类型和长度response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());// 把响应刷到客户端ctx.writeAndFlush(response);
}
netty聊天小练习
完整代码链接:https://github.com/ShimmerPig...
服务器
public class WSServer {public static void main(String[] args) throws Exception {EventLoopGroup mainGroup = new NioEventLoopGroup();EventLoopGroup subGroup = new NioEventLoopGroup();try {ServerBootstrap server = new ServerBootstrap();server.group(mainGroup, subGroup).channel(NioServerSocketChannel.class).childHandler(new WSServerInitialzer());ChannelFuture future = server.bind(8088).sync();future.channel().closeFuture().sync();} finally {mainGroup.shutdownGracefully();subGroup.shutdownGracefully();}}}
创建channel的子处理器WSServerInitialzer
加入相关的助手类handler
public class WSServerInitialzer extends ChannelInitializer<SocketChannel> {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// websocket 基于http协议,所以要有http编解码器pipeline.addLast(new HttpServerCodec());// 对写大数据流的支持 pipeline.addLast(new ChunkedWriteHandler());// 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse// 几乎在netty中的编程,都会使用到此hanlerpipeline.addLast(new HttpObjectAggregator(1024*64));// ====================== 以上是用于支持http协议 ======================// ====================== 以下是支持httpWebsocket ======================/*** websocket 服务器处理的协议,用于指定给客户端连接访问的路由 : /ws* 本handler会帮你处理一些繁重的复杂的事* 会帮你处理握手动作: handshaking(close, ping, pong) ping + pong = 心跳* 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同*/pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));// 自定义的handlerpipeline.addLast(new ChatHandler());}}
private static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
重写channelRead0方法,通过传入的TextWebSocketFrame获取客户端传入的内容。通过循环的方法对ChannelGroup中所有的channel进行回复。
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)
throws Exception {// 获取客户端传输过来的消息String content = msg.text();System.out.println("接受到的数据:" + content);// for (Channel channel: clients) {
// channel.writeAndFlush(
// new TextWebSocketFrame(
// "[服务器在]" + LocalDateTime.now()
// + "接受到消息, 消息为:" + content));
// }// 下面这个方法,和上面的for循环,一致clients.writeAndFlush(new TextWebSocketFrame("[服务器在]" + LocalDateTime.now() + "接受到消息, 消息为:" + content));}
重写handlerAdded方法,当客户端连接服务端之后(打开连接),获取客户端的channle,并且放到ChannelGroup中去进行管理。
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {clients.add(ctx.channel());
}
重写handlerRemoved方法,当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel。
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {// 当触发handlerRemoved,ChannelGroup会自动移除对应客户端的channel// clients.remove(ctx.channel());System.out.println("客户端断开,channle对应的长id为:" + ctx.channel().id().asLongText());System.out.println("客户端断开,channle对应的短id为:" + ctx.channel().id().asShortText());
}
客户端
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title></head><body><div>发送消息:</div><input type="text" id="msgContent"/><input type="button" value="点我发送" onclick="CHAT.chat()"/><div>接受消息:</div><div id="receiveMsg" style="background-color: gainsboro;"></div><script type="application/javascript">window.CHAT = {socket: null,init: function() {if (window.WebSocket) {CHAT.socket = new WebSocket("ws://192.168.1.4:8088/ws");CHAT.socket.onopen = function() {console.log("连接建立成功...");},CHAT.socket.onclose = function() {console.log("连接关闭...");},CHAT.socket.onerror = function() {console.log("发生错误...");},CHAT.socket.onmessage = function(e) {console.log("接受到消息:" + e.data);var receiveMsg = document.getElementById("receiveMsg");var html = receiveMsg.innerHTML;receiveMsg.innerHTML = html + "<br/>" + e.data;}} else {alert("浏览器不支持websocket协议...");}},chat: function() {var msg = document.getElementById("msgContent");CHAT.socket.send(msg.value);}};CHAT.init();</script></body>
</html>
测试
Netty+SpringBoot+FastDFS+Html5实现聊天App详解(一)相关推荐
- Netty+SpringBoot+FastDFS+Html5实现聊天App详解(四)
Netty+SpringBoot+FastDFS+Html5实现聊天App,项目介绍. Netty+SpringBoot+FastDFS+Html5实现聊天App,项目github链接. 本章完整代码 ...
- Netty+SpringBoot+FastDFS+Html5实现聊天App
Netty+SpringBoot+FastDFS+Html5实现聊天App github链接: https://github.com/ShimmerPig... 已将前端代码上传至github,修改a ...
- pomelo分布式聊天服务器详解
pomelo分布式聊天服务器详解 2014-01-05 11:43:49| 分类: node | 标签:pomelo pomelo聊天 nodejs分布式聊天 pomelo分布式 |举报| ...
- 视频教程-HTML5+CSS3项目实战详解-HTML5/CSS
HTML5+CSS3项目实战详解 13年软件开发经验,设计开发30多个大型软件,涉及政府.银行.电信.能源等大型软件项目. 精通J2EE体系架构,熟练使用Struts.Spring.hibernate ...
- 《HTML5网页开发实例详解》连载(四)HTML5中的FileSystem接口
HTML 5除了提供用于获取文件信息的File对象外,还添加了FileSystem相关的应用接口.FileSystem对于不同的处理功能做了细致的分类,如用于文件读取和处理的FileReader和Fi ...
- SpringBoot使用AOP,PointCut表达式详解以及使用
SpringBoot使用AOP,PointCut表达式详解以及使用 1.相关注解 2.PointCut 表达式详解 2.1 execution: 2.1 within: 2.3. this: 2.4. ...
- canvas插件_HTML系列之-HTML5新元素之Canvas详解
课程简介: 课程目标:通过本课程学习,掌握HTML5中图形绘制canvas的基本原理和使用,并利用canvas解决实际相关问题. 适用人群:具有一定html.css.javascript开发基础的人员 ...
- php仿苹果,关于8个超炫酷仿苹果应用的HTML5动画的图文详解
苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...
- html5 调用手机摄像头详解
html5 调用手机摄像头详解 首先,我们看看HTML代码结构,当然,这部分的DOM内容应该是在用户允许使用其摄像头事件出发后,动态加载生成的. 注意: 我们采用的是 640X480的分辨率,如 ...
最新文章
- Linux系统管理必备知识之查看系统用户和用户组
- NSD WINDOWS--2014.8.11
- 推荐几个BAT大佬的公众号
- UA MATH567 高维统计I 概率不等式1 Hoeffding不等式与Chernoff不等式
- IoC-spring 的灵魂(带你轻松理解IOC思想及bean对象的生成过程)
- python源码精要(2)-C代码规范
- C程序范例(2)——学生管理系统”链表“实现
- 下载eclipse出现a java_java - 运行eclipse出现问题?
- 远程办公的 33 种预测
- markdown使用markdown-viewer生成目录_谷歌浏览器查看m文件
- Eclipse Maven编译报不支持muti-catch
- redis-实现排行榜
- 【备忘】mysql优化工具
- 十道经典javaWeb面试题
- 图像 YUV与RGB格式转换
- 微信公众平台如何审核
- aruba交换机配置命令_Aruba 无线交换机基本操作命令
- java applet 打印_applet 打印常见问题与解决方法
- linux-文件和目录
- hexo 博客小功能添加-评论、萌妹纸、相册、字数统计...
热门文章
- 排序算法——直接插入排序
- linux服务器nvidia驱动的安装与卸载
- html代码中本地路径里斜杠 / 和反斜杠 \ 的区别
- zip解压mysql安装图解_Mysql安装教程-zip格式压缩包
- Leetcode题库203.移除链表元素(尾指针填充 / 虚头指针定义 c实现)
- [BUUCTF-pwn]——pwnable_orw (ORW)
- [BUUCTF-pwn]——jarvisoj_level3_x64
- 关于FragmentPager实现Fragment的滑动切换
- java数据结构排序实验报告_java数据结构与算法之插入排序详解
- Java NIO、NIO.2学习笔记