功能介绍Netty开发服务器

HTML实现客户端

实现服务端与客户端时实时交互

开发步骤

1.导包

io.netty

netty‐all

5.0.0.Alpha2

2.工程配置文件:NettyConfig

/**

* 这里放的是工程中相应的配置

*/

public class NettyConfig{

/**

* 用于存储每一个客户端接入进来时的channel对象

*/

public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

}

3.MyWebSocketHandler

public class MyWebSocketHandler extends SimpleChannelInboundHandler { private WebSocketServerHandshaker handshaker;

//请求路径

private static final String WEB_SOCKET_URL = "ws://localhost:8888/websocket";

//工程出现异常的时候调用@Override

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

cause.printStackTrace(); ctx.close(); //关闭当前连接

}

//客户端与服务器创建连接的时候调用@Override

public void channelActive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.add(ctx.channel());

System.out.println("客户端与服务器连接开启");

}

//客户端与服务器断开连接的时候调用@Override

public void channelInactive(ChannelHandlerContext ctx) throws Exception { NettyConfig.group.remove(ctx.channel());

System.out.println("客户端与服务器断开连接");

}

//服务端接收客户端发送过来的数据结束之后调用@Override

public void channelReadComplete(ChannelHandlerContext ctx) throws Exception{ ctx.flush(); //进行数据清除

}

//服务端处理客户端调用的核心方法

protected void messageReceived(ChannelHandlerContext context, Object msg) throws Exception {

//处理客户端向服务端发起http握手请求业务if(msg instanceof FullHttpRequest){

handHttpRequest(context,(FullHttpRequest) msg);

}else if(msg instanceof WebSocketFrame){

//处理websocket连接业务handWebSocketFrme(context,(WebSocketFrame)msg);

}

}

/**

* 处理客户端与服务端之前的websocket业务

* @param ctx

* @param frame

*/

private void handWebSocketFrme(ChannelHandlerContext ctx,WebSocketFrame frame){

//判断是否是关闭websocket的指令

if(frame instanceof CloseWebSocketFrame){ handshaker.close(ctx.channel(),((CloseWebSocketFrame) frame).retain());

}

//判断是否是Ping消息

if(frame instanceof PingWebSocketFrame){

//返回一个胖信息

ctx.channel().write(newPongWebSocketFrame(frame.content().retain())); return;

}

//判断是否是二进制消息,如果是二进制消息,抛出异常if(!(frame instanceof TextWebSocketFrame)){

System.out.println("目前我们不支持二进制消息");

throw new RuntimeException(this.getClass().getName()+"不支持的消息");

}

//返回应答消息

//获取客户端向服务端发送的消息

String request = ((TextWebSocketFrame)frame).text(); System.out.println("服务端收到客户端的消息===>"+request); TextWebSocketFrame tws = new TextWebSocketFrame(new

Date().toString()+ctx.channel().id()+"===>"+request);

//群发,服务端向每个上来的客户端群发消息NettyConfig.group.writeAndFlush(tws);

}

/**

* 处理客户端向服务器发起http握手请求的业务

* @param ctx

* @param req

*/

private void handHttpRequest(ChannelHandlerContext ctx,FullHttpRequest req){

// req.headers().get()

// req.decoderResult().isSuccess()

//不是websocket,就不是客户端发给服务器的Http请求if(!req.decoderResult().isSuccess()|| !

("websocket").equals(req.headers().get("Upgrade"))){

sendHttpResponse(ctx,req,new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));

return;

}

WebSocketServerHandshakerFactory wsFactory =

newWebSocketServerHandshakerFactory(WEB_SOCKET_URL,null,false); handshaker = wsFactory.newHandshaker(req);

if(handshaker==null){

WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());

}else{

handshaker.handshake(ctx.channel(),req);

}

}

/**

* 服务端向客户端响应消息

* @param ctx

* @param req

* @param res

*/

private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse res){

if(res.status().code()!=200){

ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(), CharsetUtil.UTF_8);

res.content().writeBytes(buf); buf.release();

}

//服务器向客户端发送数据

ChannelFuture f = ctx.channel().writeAndFlush(res); if(res.status().code()!=200){

f.addListener(ChannelFutureListener.CLOSE);

}

}

}

4 初始化连接各个组件:MyWebSocketChannelHandler

/**

* 初始化连接各个组件

*/

public class MyWebSocketChannelHandlerextends ChannelInitializer{

protected void initChannel(SocketChannel e) throws Exception { e.pipeline().addLast("http‐codec",new HttpServerCodec()); e.pipeline().addLast("aggregator",new HttpObjectAggregator(66636)); e.pipeline().addLast("http‐chunked",new ChunkedWriteHandler()); e.pipeline().addLast("handler",new MyWebSocketHandler());

}

}

5 程序入口

/**

* 程序的入口,负责启动应用

*/

public class Main {

public static void main(String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup();try{

ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workGroup); b.channel(NioServerSocketChannel.class); b.childHandler(new MyWebSocketChannelHandler());

System.out.println("服务端开启等待客户端连接");

Channel ch = b.bind(8888).sync().channel(); ch.closeFuture().sync();

} catch (Exception e) {

e.printStackTrace();

} finally {

//优雅的退出程序bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();

}

}

}

6 web端测试代码

WebSocket客户端

var socket; if(!window.WebSocket){

window.WebSocket = window.MozWebSocket;

}

if(window.WebSocket){

socket = new WebSocket("ws://localhost:8888/websocket"); socket.onmessage = function (event) {

var ta = document.getElementById("responseContext"); ta.value += event.data +"\r\n";

}

socket.onopen = function (event) {

var ta = document.getElementById("responseContext"); ta.value = "您浏览器支持webSoceket,请进行后续 操作\r\n";

}

socket.onclose = function (event) {

var ta = document.getElementById("responseContext"); ta.value = "";

ta.value = "webSoceket连接已经关闭";

}

}else{

console.debug("浏览器不支持webSocket")

}

function send() {

var message = document.getElementById("message").value; if(!window.WebSocket){

return;

}

if(socket.readyState == WebSocket.OPEN){ socket.send(message)

}else{

alert("连接没有建立成功!");

}

}


客户端接收到服务端返回的消息

java netty html_源码时代JAVA干货分享|带你用Netty框架实现WebSocket通信相关推荐

  1. 源码时代 UI干货分享 | 如何用AI制作出迪士尼电影里的毛绒文字效果!!

    AI 制作毛绒文字效果 今天给大家带来用AI制作毛发文字的教程希望对大家有用. 1.首先在AI中绘制出要做的文字路径,关闭填充属性只剩下描边属性,如下图中的路径文字"8" 再画出2 ...

  2. 源码时代UI干货分享|史上最全的HTML三大列表的写法总结,快来收藏吧!

    今天给大家介绍网页中列表的写法,网页中的列表共分三种,分别是无序列表.有序列表和定义列表. 无序列表 什么是无序列表? 无序列表就是没有顺序的列表,主要用于描述一组没有顺序的数据. 无序列表的语法 语 ...

  3. 源码时代UI干货分享| AE如何实现文字消散效果?看这一篇就够了!

    首先: 新建合成 2.新建一个纯色图层做背景(如果自带背景可以忽略) 3.新建文本图层 4.打上文字,调整文字大小,让文字在画布中居中 然后: 5.给文字添加一个蒙版 6.在0秒的位置的蒙版路径打上关 ...

  4. 源码时代UI干货分享|Axure基础教程

    主界面介绍 知识重点 一.页面的切换 热区:就是可做交互的区域.动态面板:多种状态,可以反复切换. 第一步:鼠标选择热区,鼠标左键拖拽到画布中,调整到合适位置,合适大小第二步:在图层面板中,修改热区图 ...

  5. 源码时代UI干货 | 只用5步教会你制作《这就是街舞》风格的字体设计

    PS技巧分享: 5步教你快速学会制作<这就是街舞>风格的字体设计 1.首先用潮字社凌渡鲲鹏简打出一个基础字体 2.再字上面新建一层,给他剪切进去 我们在新建的这一层上,用画笔在笔画上,涂上 ...

  6. 源码时代UI干活分享| ps新手入门案例,手把手教你在白板上制出写实图标鸡蛋

    写实图标鸡蛋 1.最终效果 2.第一步需要先去百度图片寻找找参考 3.分析出它的颜色以及高光和阴影部分 4.分析过后开始制作 新建画布800 X 600px 分辨率72 5.给背景填充颜色 偏黄一点的 ...

  7. java工具类源码阅读,java学习日记第二天(实用的工具类和源码解析一Arrays)

    本帖最后由 三木猿 于 2020-9-18 11:17 编辑 每日名言 学者须先立志.今日所以悠悠者,只是把学问不曾做一件事看,遇事则且胡乱恁地打过了,此只是志不立. --朱熹 工作中经常会用到一些工 ...

  8. java java.lang.enum_源码阅读-java基础-java.lang.Enum

    1.引言 枚举类型是 JDK 5 之后引进的一种非常重要的引用类型,可以用来定义一系列枚举常量.相比与常量(public static final定义),在安全性.指意性.可读性方面更胜一筹.另外它可 ...

  9. java桌面通讯录源码_TONGXUNLU JAVA通讯录源码 JAVA课程设计源码 讯友桌面通讯录 通讯录管理 - 下载 - 搜珍网...

    讯友桌面通讯录/.classpath 讯友桌面通讯录/.project 讯友桌面通讯录/.settings/org.eclipse.jdt.core.prefs 讯友桌面通讯录/bin/com/zzk ...

最新文章

  1. hive工作记录-20180513
  2. UIImage指定区域自由拉伸
  3. Linux集群服务知识点总结及通过案例介绍如何实现高性能web服务(三)
  4. PHP 直接在共享内存中存储数据集
  5. 嵌入式davinci电路元素基础和PWM模块
  6. MOSS 2010:Visual Studio 2010开发体验(16)——客户端对象模型
  7. 游戏开发--开源18---Volity|PhiloGL|impactJs|createjs|C...
  8. esp8266应用教程——TFT LCD显示
  9. 手把手教你:安装svn出现could not write value to key的错误
  10. 基于Python实现的网上购书功能的网站后端
  11. 解决ASUS P5GC-MX/1333声卡驱动不能正常安装的问题
  12. 【线性系统理论】0.线性系统基本概念(1)
  13. 如何玩转YouTube
  14. 如何获取国际标准时间
  15. gfsdgfsragf
  16. 涵盖从java入门到深入架构,Linux、云计算、分布式、大数据Hadoop、ios、Android、互联网技术应有尽有
  17. 关于本人的网络地址请移步简书
  18. 响应式织梦模板律师事务所网站
  19. 有哪些你看过五遍以上的电影?
  20. MySQL:慢查询日志

热门文章

  1. [渝粤教育] 中国地质大学 材料力学 复习题 (2)
  2. 【渝粤题库】国家开放大学2021春2786初级西方经济学题目
  3. [渝粤题库]陕西师范大学《幼儿园语言教育》作业
  4. 物联网中的无线通信模块到底是什么
  5. Promise 学习心得
  6. Mac--PHP已经开启gd扩展验证码不显示
  7. 牛客网 2018年全国多校算法寒假训练营练习比赛(第五场) H.Tree Recovery-完全版线段树(区间更新、区间求和)...
  8. GetSystemInfo()
  9. Windows负载机JVM 远程监控Linux服务器下tomcat
  10. DB2 SQL性能调优秘笈pdf