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进阶之Linux破解密码、yum源配置、防火墙设置及源码包安装
一.老师语录: 所有要求笔试的公司都是垃圾公司 笔试(是考所有的涉及到的点) 要有自己的卖点.专长(给自己个标签)(至少一个) 生产环境中,尽量使用mv(mv到一个没用的目录下),少使用rm 二.防火 ...
- Elasticsearch + Logstash + Kibana +Redis +Filebeat 单机版日志收集环境搭建
1.前置工作 1.虚拟机环境简介 Linux版本:Linux localhost.localdomain 3.10.0-862.el7.x86_64 #1 SMP Fri Apr 20 16:44:2 ...
- 彻底弄懂HTTP缓存机制及原理【转载】
前言 Http 缓存机制作为 web 性能优化的重要手段,对于从事 Web 开发的同学们来说,应该是知识体系库中的一个基础环节,同时对于有志成为前端架构师的同学来说是必备的知识技能.但是对于很多前端同 ...
- 用virtualenv建立Python独立开发环境
1.用pip安装virtualenv sudo apt-get install python-virtualenv 2.1 创建python2的虚拟环境,进入要创建虚拟环境的目录下,我是放在/home ...
- 十一、.net core(.NET 6)搭建ElasticSearch(ES)系列之ElasticSearch、head-master、Kibana环境搭建
搭建ElasticSearch+Kibana环境 前提条件:已经配置好JDK环境以及Nodejs环境.如果还未配置,请查看我的上一篇博客内容,有详细配置教程. 先下载ElasticSearch(以下文 ...
- 5G通讯与芯片
5G通讯与芯片 美国商务部可能接近达成一项新的规则,允许美国公司与华为重启谈判,在共同制定下一代通信技术5G标准方面进行合作. 华为美国首席安全官安迪·珀迪(Andy Purdy)向第一财经记者独家回 ...
- 3D-LaneNet:端到端三维多车道检测ICCV2019
3D-LaneNet:端到端三维多车道检测ICCV2019 3D-LaneNet: End-to-End 3D Multiple Lane Detection 论文链接: http://openacc ...
- MindInsight计算图可视设计
MindInsight计算图可视设计 特性背景 计算图可视的功能,主要协助开发者在下面这些场景中使用. 开发者在编写深度学习神经网络的代码时,可以使用计算图的功能查看神经网络中算子的数据流走向,以及模 ...
- 尚硅谷Java——宋红康笔记【day1-day5】
day1 注释 1.java规范的三种注释方式: 单行注释 多行注释 文档注释(java特有) 2. 单行注释和多行注释的作用: ① 对所写的程序进行解释说明,增强可读性.方便自己,方便别人 ② 调试 ...
- 【NX二次开发】 删除面操作
录制修改封装删除面 DeleteFaces 1 #include <uf_defs.h> 2 #include <NXOpen/NXException.hxx> 3 #incl ...