一、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. linux 修改IP, DNS -(转自fighter)

    linux下修改IP.DNS.路由命令行设置 ubuntu 版本命令行设置IP cat /etc/network/interfaces # This file describes the networ ...

  2. linux stat函数讲解 -(转自秋水Leo)

    stat函数讲解表头文件:    #include <sys/stat.h>             #include <unistd.h>定义函数:    int stat( ...

  3. C语言进阶日志二

    1.一个功能模块最好使用一个文件夹包含 2.基本就需要几个文件,比如定时器取反  LED: bsp_led.c 和 bsp_led.h : 包含你需要的led外设GPIO的初始化代码 led_it.c ...

  4. spark算子优化

    一.在聚合前在map端先预聚合 使用reduceByKey/aggregateByKey代替groupByKey 二.一次处理一个分区的数据,不过要注意一个分区里的数据不要太大,不然会报oom * 使 ...

  5. 本地软件仓库配置及NFS安装

    [root@localhost ~]# mount /dev/cdrom /mnt mount: /dev/sr0 is write-protected, mounting read-only [ro ...

  6. Python单元测试简介及Django中的单元测试

    Python单元测试简介及Django中的单元测试 单元测试负责对最小的软件设计单元(模块)进行验证,unittest是Python自带的单元测试框架. 单元测试与功能测试都是日常开发中必不可少的部分 ...

  7. gin使用validator库参数校验若干实用技巧

    validator库参数校验若干实用技巧 本文介绍了使用validator库做参数校验的一些十分实用的使用技巧,包括翻译校验错误提示信息.自定义提示信息的字段名称.自定义校验方法等. validato ...

  8. nvJPEG库

    nvJPEG库 GPU加速的JPEG解码器,编码器和代码转换器 nvJPEG库是高性能的GPU加速库,用于解码,编码和转码JPEG格式的图像.nvJPEG2000库用于解码JPEG 2000格式的图像 ...

  9. PyTorch 数据并行处理

    PyTorch 数据并行处理 可选择:数据并行处理(文末有完整代码下载) 本文将学习如何用 DataParallel 来使用多 GPU. 通过 PyTorch 使用多个 GPU 非常简单.可以将模型放 ...

  10. 适用于Windows和Linux的Yolo-v3和Yolo-v2(下)

    适用于Windows和Linux的Yolo-v3和Yolo-v2(下) 如何训练(检测自定义对象): (培养老YOLO V2 yolov2-voc.cfg,yolov2-tiny-voc.cfg,yo ...