一、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的支持的更多相关文章

  1. 使用ASP.NET Web API自带的类库实现对CORS的支持(在开发中使用这种方式)(转载)

    在<通过扩展让ASP.NET Web API支持W3C的CORS规范>中我们通过自定义的HttpMessageHandler为ASP.NET Web API赋予了跨域资源共享的能力,具体来 ...

  2. 如何在iOS上实现对HTTPS的支持(转)

    原文地址:http://blog.5ibc.net/p/101504.html 首先,需要明确你使用HTTP/HTTPS的用途,因为OSX和iOS平台提供了多种API,来支持不同的用途,官方文档< ...

  3. qml实现对SSL的支持(使用msys2,同时支持32和64位)超详细 good

    首先准备环境.两种方法,使用mingw64 或者VS 直接放上下载地址https://sourceforge.net/projects/msys2/我下载的是msys2-x86_64-20161025 ...

  4. .net core 和 WPF 开发升讯威在线客服与营销系统:实现对 IE8 的完全完美支持 【干货】

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...

  5. Netty对WebSocket的支持(五)

    Netty对WebSocket的支持(五) 一.WebSocket简介 在Http1.0和Http1.1协议中,我们要实现服务端主动的发送消息到网页或者APP上,是比较困难的,尤其是现在IM(即时通信 ...

  6. Google帮助IE浏览器实现对SVG支持

    可缩放矢量图形(SVG)的意识就是一个用于描述二维矢量图形的一种开放图形格式. SVG现在已经能够广泛得应用到许多的项目当中,包括KDE和维基百科等.但是 Internet Explorer浏览器的内 ...

  7. 基于spring-boot和docker-java实现对docker容器的动态管理和监控[附完整源码下载]

    ​ (我是个封面) docker简介 Docker 是一个开源的应用容器引擎,和传统的虚拟机技术相比,Docker 容器性能开销极低,因此也广受开发者喜爱.随着基于docker的开发者越来越多,doc ...

  8. 基于DevExpress实现对PDF、Word、Excel文档的预览及操作处理

    http://www.cnblogs.com/wuhuacong/p/4175266.html 在一般的管理系统模块里面,越来越多的设计到一些常用文档的上传保存操作,其中如PDF.Word.Excel ...

  9. Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

    本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...

随机推荐

  1. 10.11 arping:发送arp请求

    arping命令 是用于发送arp请求到一个相邻主机的工具,arping使用arp数据包检查局域网内所有设备的硬件地址.  arping 命令的参数选项及说明 -c <次数>       ...

  2. ThinkPHP 全局异常处理

    wqy的笔记:http://www.upwqy.com/details/273.html 在thinkphp6 和 thinkphp5 全局异常处理 稍有不同 ThinkPHP6 在 tp6 中 框架 ...

  3. 在vue中使用prismjs

    wqy的笔记:http://www.upwqy.com/details/261.html 作者:wqy 1 首先在项目中安装prismjs插件: cnpm install prismjs -S 2 安 ...

  4. AIoT开放平台及应用

    AIoT开放平台及应用 阿里AIoT开放平台,是阿里云IoT面向开发者的能力接入渠道,开发者可以在这里完成能力的申请.开通.部署.配置和集成开发等一些列工作.这些能力并不的独立交付,而是通过关联到行业 ...

  5. MindSpore整体架构介绍

    MindSpore整体架构介绍 MindSpore框架架构总体分为MindSpore前端表示层.MindSpore计算图引擎和MindSpore后端运行时三层. MindSpore前端表示层(Mind ...

  6. MinkowskiEngine基准测试

    MinkowskiEngine基准测试 介绍卷积层和小型U网络的前馈和后馈通过时间.可以将具有相同张量步幅,步幅和内核偏移的内核映射重新用于其他层,可以在大型nueral网络中使用的所有层上,分摊此页 ...

  7. Pass Infrastructure基础架构(上)

    Pass Infrastructure基础架构(上) Operation Pass OperationPass : Op-Specific OperationPass : Op-Agnostic De ...

  8. 2019个嵌入式市场研究,持续的C/C++优势

    2019个嵌入式市场研究,持续的C/C++优势 2019 Embedded Markets Study reflects emerging technologies, continued C/C++ ...

  9. 编译原理-确定有穷自动机(deterministic finite automata ,DFA)

    是一个五元组 M=(S,∑,f,S0,F) 其中 S:有穷状态集 ∑:输入字母表(有穷) f:状态转换函数.f(S,a)=S' 是单值部分映射,每个状态面临一个输入符号时,转入的后继状态是确定的. S ...

  10. 【NX二次开发】Block UI 选项卡控件

    [NX二次开发]Block UI 选项卡控件