Netty5 + WebSocket 练习
2016-03-07 08:44
288 查看
1. 了解WebSocket知识
略
2. websocket实现系统简单反馈时间
WebSocketServerHandler.java
WebSocketServerHandler.java
WebSocketServer.html (这个随便放都可以,到时候双击打开这个即可,不由服务器提供)
运行结果
View Code
运行结果,依次运行1,2,3
服务器打印结果
参考资料:
《Netty 权威指南》
https://zh.wikipedia.org/wiki/WebSocket
https://www.zhihu.com/question/20215561
http://waylau.com/netty-websocket-chat/
本文地址:/article/6193172.html
略
2. websocket实现系统简单反馈时间
WebSocketServerHandler.java
package com.jieli.nettytest.websocketserver; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.stream.ChunkedWriteHandler; public class WebSocketServer { public void run(int port){ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //HttpServerCodec将请求和应答消息编码或解码为HTTP消息 //通常接收到的http是一个片段,如果想要完整接受一次请求所有数据,我们需要绑定HttpObjectAggregator //然后就可以收到一个FullHttpRequest完整的请求信息了 //ChunkedWriteHandler 向客户端发送HTML5文件,主要用于支持浏览器和服务器进行WebSocket通信 //WebSocketServerHandler自定义Handler ch.pipeline().addLast("http-codec", new HttpServerCodec()) .addLast("aggregator", new HttpObjectAggregator(65536)) //定义缓冲大小 .addLast("http-chunked", new ChunkedWriteHandler()) .addLast("handler", new WebSocketServerHandler()); } }); ChannelFuture f = b.bind(port).sync(); System.out.println("start..."); f.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } public static void main(String[] args) { new WebSocketServer().run(7777); } }
WebSocketServerHandler.java
package com.jieli.nettytest.websocketserver; import java.util.logging.Level; import java.util.logging.Logger; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpHeaderUtil; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketFrame; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; import io.netty.util.CharsetUtil; public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object>{ /** * 日志 */ private static final Logger logger = Logger.getLogger(WebSocketServerHandler.class.getName()); /** * 全局websocket */ private WebSocketServerHandshaker handshaker; @Override protected void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception { //普通HTTP接入 if(msg instanceof FullHttpRequest){ handleHttpRequest(ctx, (FullHttpRequest) msg); }else if(msg instanceof WebSocketFrame){ //websocket帧类型 已连接 //BinaryWebSocketFrame CloseWebSocketFrame ContinuationWebSocketFrame //PingWebSocketFrame PongWebSocketFrame TextWebScoketFrame handleWebSocketFrame(ctx, (WebSocketFrame) msg); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest request){ //如果http解码失败 则返回http异常 并且判断消息头有没有包含Upgrade字段(协议升级) if(!request.decoderResult().isSuccess() || (!"websocket".equals( request.headers().get("Upgrade"))) ){ sendHttpResponse(ctx, request, new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); return ; } //构造握手响应返回 WebSocketServerHandshakerFactory ws = new WebSocketServerHandshakerFactory("", null, false); handshaker = ws.newHandshaker(request); if(handshaker == null){ //版本不支持 WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); }else{ handshaker.handshake(ctx.channel(), request); } } /** * websocket帧 * @param ctx * @param frame */ private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame){ //判断是否关闭链路指令 if(frame instanceof CloseWebSocketFrame){ handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain()); return ; } //判断是否Ping消息 -- ping/pong心跳包 if(frame instanceof PingWebSocketFrame){ ctx.channel().write(new PongWebSocketFrame(frame.content().retain())); return ; } //本程序仅支持文本消息, 不支持二进制消息 if(!(frame instanceof TextWebSocketFrame)){ throw new UnsupportedOperationException( String.format("%s frame types not supported", frame.getClass().getName())); } //返回应答消息 text文本帧 String request = ((TextWebSocketFrame) frame).text(); //打印日志 if(logger.isLoggable(Level.FINE)){ logger.fine(String.format("%s received %s", ctx.channel(), request)); } //发送到客户端websocket ctx.channel().write(new TextWebSocketFrame(request + ", 欢迎使用Netty WebSocket服务, 现在时刻:" + new java.util.Date().toString())); } /** * response * @param ctx * @param request * @param response */ private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response){ //返回给客户端 if(response.status().code() != HttpResponseStatus.OK.code()){ ByteBuf buf = Unpooled.copiedBuffer(response.status().toString(), CharsetUtil.UTF_8); response.content().writeBytes(buf); buf.release(); HttpHeaderUtil.setContentLength(response, response.content().readableBytes()); } //如果不是keepalive那么就关闭连接 ChannelFuture f = ctx.channel().writeAndFlush(response); if(!HttpHeaderUtil.isKeepAlive(response) || response.status().code() != HttpResponseStatus.OK.code()){ f.addListener(ChannelFutureListener.CLOSE); } } /** * 异常 出错 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
WebSocketServer.html (这个随便放都可以,到时候双击打开这个即可,不由服务器提供)
<html> <head> <meta charset="utf-8"> <title>Netty websocket 时间服务器</title> </head> <body> <form action="" onsubmit="return false;"> <input type="text" name="message" value="..."/> <br> <input type="button" value="send" value="发送websocket请求消息" onclick="send(this.form.message.value);" /> <hr color="blue"> <h3>服务器返回信息</h3> <textarea id="responseText" rows="10" cols=""></textarea> </form> </body> <script type="text/javascript"> var socket; if(!window.WebSocket){ window.WebSocket = window.MozWebSocket; } if(window.WebSocket){ socket = new WebSocket("ws://localhost:7777/websocket"); socket.onmessage = function(event){ var ta = document.getElementById('responseText'); ta.value=""; ta.value=event.data; }; socket.onopen = function(event){ var ta = document.getElementById('responseText'); ta.value = "打开websocket服务正常"; } socket.onclose = function(event){ var ta = document.getElementById('responseText'); ta.value=""; ta.value="websocket关闭"; } }else{ alert("对不起,您的浏览器不支持WebSocket."); } function send(message){ if(!window.WebSocket){ return ; } if(socket.readyState == WebSocket.OPEN){ socket.send(message); }else{ alert("WebSocket 连接创建失败."); } } </script> </html>
运行结果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>WebSocket Chat</title> </head> <body> <script type="text/javascript"> var socket; if (!window.WebSocket) { window.WebSocket = window.MozWebSocket; } if (window.WebSocket) { socket = new WebSocket("ws://localhost:8080/ws"); socket.onmessage = function(event) { var ta = document.getElementById('responseText'); ta.value = ta.value + '\n' + event.data }; socket.onopen = function(event) { var ta = document.getElementById('responseText'); ta.value = "连接开启!"; }; socket.onclose = function(event) { var ta = document.getElementById('responseText'); ta.value = ta.value + "连接被关闭"; }; } else { alert("你的浏览器不支持 WebSocket!"); } function send(message) { if (!window.WebSocket) { return; } if (socket.readyState == WebSocket.OPEN) { socket.send(message); } else { alert("连接没有开启."); } } </script> <form onsubmit="return false;"> <h3>WebSocket 聊天室:</h3> <textarea id="responseText" style="width: 500px; height: 300px;"></textarea> <br> <input type="text" name="message" style="width: 300px" value="Welcome to localhost"> <input type="button" value="发送消息" onclick="send(this.form.message.value)"> <input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="清空聊天记录"> </form> <br> Netty SEO 优化 Netty 是什么 Netty 怎么样 Netty4 Netty5 区别 Netty 效率 Netty 版本区别 Netty 和 Mina Netty 网络编程 Netty Java 网络编程 Netty Java Socket NIO NIO 编程 Netty NIO 开发 Netty3 Netty4 Netty5 Netty 好处 Netty 一般注意什么 Netty 例子程序 Netty Hello World Netty 聊天程序 Netty Web HTML HTTP FTP SSL Netty UDP TCP WebSocket 练习 Netty 连接数 Netty 源码 <br> </body> </html>
View Code
运行结果,依次运行1,2,3
服务器打印结果
参考资料:
《Netty 权威指南》
https://zh.wikipedia.org/wiki/WebSocket
https://www.zhihu.com/question/20215561
http://waylau.com/netty-websocket-chat/
本文地址:/article/6193172.html
相关文章推荐
- EXTJS 中 anchor 的用法
- Afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框架,使其更加简单易用
- javascript ajax
- Netty4.0学习笔记系列之三:构建简单的http服务
- C语言——项目规范
- Delphi 6常用日期与时间函数
- sql语句
- HTML DOM Anchor 对象
- android studio 报Android NDK: Aborting... . Stop.
- 算法练习-猜算式
- 静态成员
- Delphi常用日期函数
- C#基础
- Java .作业1
- 电子竞技:粉丝生意之后的IP大战
- 如何修改Linux服务器的MySQL数据库root密码
- 设计模式
- C#语言基础—运算符
- Java堆内存
- 20160307 Windows下mingw32-make找不到QApplication的解决办法