Netty实现对Websocket的支持
一、WebSocket的简介及优势
WebSocket 是一种网络通信协议。RFC6455 定义了它的通信标准。WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
首先可以看下HTTP协议的有哪些不好的地方:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。
为了解决这些痛点,WebSocket就应运而生了。WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。
二、WebSocket客户端API
2.1 WebSocket 构造函数
var Socket=new WebSocket("ws://localhost:20000/web");
2.2 WebSocket 属性
以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:
| 属性 | 描述 |
|---|---|
| Socket.readyState | 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。 |
| Socket.bufferedAmount | 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。 |
2.3 WebSocket 事件
以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:
| 事件 | 事件处理程序 | 描述 |
|---|---|---|
| open | Socket.onopen | 连接建立时触发 |
| message | Socket.onmessage | 客户端接收服务端数据时触发 |
| error | Socket.onerror | 通信发生错误时触发 |
| close | Socket.onclose | 连接关闭时触发 |
2.4 WebSocket 方法
以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:
| 方法 | 描述 |
|---|---|
| Socket.send() | 使用连接发送数据 |
| Socket.close() | 关闭连接 |
三、WebSocket客户端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Netty WebSocket</title>
</head>
<body>
<br>
<script type="text/javascript">
var websocket;
if(!window.WebSocket){
window.WebSocket=window.MozWebSocket;
}
if(window.WebSocket){
websocket=new WebSocket("ws://localhost:20000/web");
websocket.onmessage=function (event) {
console.log("websocket接受消息"+event.data);
var text=document.getElementById('responseText');
text.value="";
text.value=event.data;
}
websocket.onopen=function (event) {
console.log("websocket打开");
var text=document.getElementById('responseText');
text.value="";
text.value="打开websocket服务正常";
}
websocket.onclose=function (event) {
console.log("websocket关闭");
var text=document.getElementById('responseText');
text.value="";
text.value="关闭websocket服务";
}
websocket.onerror=function (event) {
console.log("websocket异常");
var text=document.getElementById('responseText');
text.value="";
text.value="websocket服务异常"; }
}else{
alert("你的浏览器不支持WebSocket");
} function send(message) {
if(websocket){
if(websocket.readyState==WebSocket.OPEN){
console.log("通过websocket发送消息");
websocket.send(message);
}
}else{
alert("未建立websocket连接");
}
}
</script> <form onsubmit="return false;">
<input type="text" name="message" value="Netty实践"/>
<br><br>
<input type="button" value="发送消息" onclick="send (this.form.message.value)"/>
<h3>应答消息</h3>
<textarea id="responseText" style="width: 500px;height: 300px;"></textarea>
</form> </body>
</html>
四、netty服务端代码
4.1 netty启动类
public class NettyServer {
public static void main(String[] args) throws Exception{
//服务器启动
new NettyServer().start(20000);
}
public void start(int port) throws Exception{
//用于监听连接的线程组
EventLoopGroup bossGroup=new NioEventLoopGroup();
//用于发送接收消息的线程组
EventLoopGroup workGroup=new NioEventLoopGroup();
try{
//启动类引导程序
ServerBootstrap b=new ServerBootstrap();
//绑定两个线程组
b.group(bossGroup,workGroup);
//设置非阻塞,用它来建立新accept的连接,用于构造serverSocketChannel的工厂类
b.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel){
ChannelPipeline channelPipeline=channel.pipeline();
// HttpServerCodec:将请求和应答消息解码为HTTP消息
channelPipeline.addLast(new HttpServerCodec());
// HttpObjectAggregator:将HTTP消息的多个部分合成一条完整的HTTP消息
channelPipeline.addLast(new HttpObjectAggregator(65536));
// ChunkedWriteHandler:向客户端发送HTML5文件
channelPipeline.addLast(new ChunkedWriteHandler());
//在管道中添加自己实现的Handler处理类
channelPipeline.addLast(new WebsocketServerHandler());
}
});
Channel channel=b.bind(port).sync().channel();
System.out.println("服务器启动端口:"+port);
channel.closeFuture().sync();
}finally {
workGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
4.2 netty的业务处理的Handler类
public class WebsocketServerHandler extends SimpleChannelInboundHandler<Object> {
private WebSocketServerHandshaker handshaker;
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
//传统的http接入
if(o instanceof FullHttpRequest){
handleHttpRequest(channelHandlerContext,(FullHttpRequest) o);
}
//webSocket接入
else if(o instanceof WebSocketFrame){
handleWebsocketFrame(channelHandlerContext,(WebSocketFrame) o);
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req){
//构造握手响应返回
WebSocketServerHandshakerFactory webSocketServerHandshakerFactory=new WebSocketServerHandshakerFactory("ws://localhost:20000/web",null,false);
handshaker=webSocketServerHandshakerFactory.newHandshaker(req);
handshaker.handshake(ctx.channel(),req);
}
private void handleWebsocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame){
//判断是否是链路关闭消息
if(frame instanceof CloseWebSocketFrame){
handshaker.close(ctx.channel(),(CloseWebSocketFrame) frame.retain());
return;
}
//判断是否是ping消息
if(frame instanceof PingWebSocketFrame){
ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
return;
}
//文本消息处理
String request=((TextWebSocketFrame)frame).text();
System.out.println("接受的信息是:"+request);
String date=new Date().toString();
//将接收消息写回给客户端
ctx.channel().write(new TextWebSocketFrame("现在时刻:"+date+"发送了:"+request));
}
}
五、运行成功截图

参考资料:
https://www.cnblogs.com/jingmoxukong/p/7755643.html
http://www.ruanyifeng.com/blog/2017/05/websocket.html
Netty实现对Websocket的支持的更多相关文章
- 使用ASP.NET Web API自带的类库实现对CORS的支持(在开发中使用这种方式)(转载)
在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中我们通过自定义的HttpMessageHandler为ASP.NET Web API赋予了跨域资源共享的能力,具体来 ...
- 如何在iOS上实现对HTTPS的支持(转)
原文地址:http://blog.5ibc.net/p/101504.html 首先,需要明确你使用HTTP/HTTPS的用途,因为OSX和iOS平台提供了多种API,来支持不同的用途,官方文档< ...
- qml实现对SSL的支持(使用msys2,同时支持32和64位)超详细 good
首先准备环境.两种方法,使用mingw64 或者VS 直接放上下载地址https://sourceforge.net/projects/msys2/我下载的是msys2-x86_64-20161025 ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:实现对 IE8 的完全完美支持 【干货】
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- Netty对WebSocket的支持(五)
Netty对WebSocket的支持(五) 一.WebSocket简介 在Http1.0和Http1.1协议中,我们要实现服务端主动的发送消息到网页或者APP上,是比较困难的,尤其是现在IM(即时通信 ...
- Google帮助IE浏览器实现对SVG支持
可缩放矢量图形(SVG)的意识就是一个用于描述二维矢量图形的一种开放图形格式. SVG现在已经能够广泛得应用到许多的项目当中,包括KDE和维基百科等.但是 Internet Explorer浏览器的内 ...
- 基于spring-boot和docker-java实现对docker容器的动态管理和监控[附完整源码下载]
(我是个封面) docker简介 Docker 是一个开源的应用容器引擎,和传统的虚拟机技术相比,Docker 容器性能开销极低,因此也广受开发者喜爱.随着基于docker的开发者越来越多,doc ...
- 基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理
http://www.cnblogs.com/wuhuacong/p/4175266.html 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel ...
- Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问
本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...
随机推荐
- linux stat函数讲解 -(转自秋水Leo)
stat函数讲解表头文件: #include <sys/stat.h> #include <unistd.h>定义函数: int stat( ...
- python3 xlrd包的用法
一.xlrd的安装 pip install xlrd 二.xlrd使用介绍 1.导入模块 import xlrd 2.打开Excel文件,实例化为readbook readbook = xlrd.op ...
- #undef 与 exit(0) 使用
#undef 与 #defined 反,实际使用中较多的是当你需要使用自己定义的标准C里面已经的函数时可以这样操作: exit(0)和exit(1)是系统判断函数是否有正常的退出,一般0表示正常的退 ...
- crontab 的简要介绍
1.概述: crontab 用于周期性被执行的指令,该指令从标准设备输入指令,并将指令存放在crontab文件中,供之后读取和执行. 与crontab相关的文件一共有三个: /etc/crontab ...
- Jquery 常用方法及实例(Day_15)
想要做一件事,永远都不要怕晚.只要你开始做了,就不晚. 而若是你不开始,仅仅停留在思考.犹豫甚至焦虑的状态,那就永远都是零. mouseover() / mouserout() 当鼠标进入 / 离开某 ...
- GStreamer 1.18.4稳定的错误修复版本
GStreamer 1.18.4稳定的错误修复版本GStreamer团队宣布最喜欢的跨平台多媒体框架的稳定的1.18版本系列中的另一个错误修复版本!此版本仅包含错误修复和重要的安全修复程序,并且从1. ...
- Deeplearning知识蒸馏
Deeplearning知识蒸馏 merge paddleslim.dist.merge(teacher_program, student_program, data_name_map, place, ...
- NVIDIA GPU的快速傅立叶变换
NVIDIA GPU的快速傅立叶变换 cuFFT库提供GPU加速的FFT实现,其执行速度比仅CPU的替代方案快10倍.cuFFT用于构建跨学科的商业和研究应用程序,例如深度学习,计算机视觉,计算物理, ...
- Comparison of Laser SLAM and Visual SLAM
Comparison of Laser SLAM and Visual SLAM 目前,SLAM技术广泛应用于机器人.无人机.无人机.AR.VR等领域,依靠传感器可以实现机器的自主定位.测绘.路径规划 ...
- 学习响应式编程 Reactor (3) - reactor 基础
Reactor Reactor 项目的主要 artifact 是 reactor-core,这是一个基于 Java 8 的实现了响应式流规范的响应式库. Reactor 提供了实现 Publisher ...