Netty学习——通过websocket编程实现基于长连接的双攻的通信
Netty学习(一)基于长连接的双攻的通信,通过websocket编程实现
效果图,客户端和服务器端建立起长连接,客户端发送请求,服务器端响应
但是目前缺少心跳,如果两个建立起来的连接,一个断网之后,另外一个是感知不到对方已经断掉的。以后使用心跳技术来进行连接检测
须知:
状态码101,代表 协议转换,从HTTP协议升级为WebSocket协议
HTTP协议,一般访问的时候:是 Http://localhost:8080/ws
WebSocket协议,访问的时候,需要是:ws://localhost:8080/ws
实现代码:
服务器端:
package com.dawa.netty.fifthexample; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; import java.net.InetSocketAddress; /**
* @Title: MyServer
* @Author: 大娃
* @Date: 2019/11/28 14:02
* @Description:
*/
public class MyServer {
public static void main(String[] args) throws Exception{
//定义一个线程组 , 事件循环组 。 异步的NIO , 就是一个死循环。
EventLoopGroup bossGroutp = new NioEventLoopGroup(); //不断的接受连接,但是不处理
EventLoopGroup workerGroup = new NioEventLoopGroup(); // 完成后续处理,把结果返回给客户端
try { //服务端,启动类
ServerBootstrap serverBootstrap = new ServerBootstrap();
//group方法,有两个参数的,有一个参数的
serverBootstrap.group(bossGroutp, workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new WebSocketChannelInitializer()); //字处理器,自己 定义的 ChannelFuture channelFuture = serverBootstrap.bind(new InetSocketAddress(8899)).sync();
channelFuture.channel().closeFuture().sync();
} finally {
//优雅关闭、
bossGroutp.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
package com.dawa.netty.fifthexample; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler; /**
* @Title: WebSocketChannelInitializer
* @Author: 大娃
* @Date: 2019/11/28 14:06
* @Description:
*/
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());//新的处理器 块
pipeline.addLast(new HttpObjectAggregator(8192)); //将分开的段,给聚合到一起,形成完整的HTTP响应。很重要的一个对象,在处理HTTP的时候
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
pipeline.addLast(new TextWebSocketFrameHandler());
}
}
package com.dawa.netty.fifthexample; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import java.time.LocalDateTime; /**
* @Title: TextWebSocketFrameHandler
* @Author: 大娃
* @Date: 2019/12/2 08:33
* @Description:
*/
public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { /**
*
* @param ctx 上下文对象
* @param msg //文本帧对象
* @throws Exception 抛异常
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("收到消息:"+msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:"+ LocalDateTime.now() )); //不能直接传入 字符串.因为不同协议的规范不同,websocket要求要传回这种的对象
} @Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded:" + ctx.channel().id().asLongText());//每一个channel 都有一个唯一的id值与其对应
} @Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("HandlerRemoved:" + ctx.channel().id().asLongText());
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.channel().close();
}
}
客户端(使用HTML,JS来代替模拟客户端)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>websocket客户端</title>
</head>
<body>
<!-- -->
<script type="text/javascript">
//使用浏览器,进行websocket服务器端的访问
var socket;
if (window.WebSocket) {//判断浏览器是否支持websocket
socket = new WebSocket("ws:localhost:8899/ws"); //建立websocket连接
socket.onmessage = function (ev) { //如果socket收到消息,这个onmessage方法就会被回调
var ta = document.getElementById('responseText');
ta.value = ta.value + "\n" + ev.data;
}; socket.onopen=function (ev) {//当连接被打开的时候,执行的回调
var ta = document.getElementById('responseText');
ta.value = "连接开启!";
}; socket.onclose = function (ev) {
var ta = document.getElementById('responseText');
ta.value = ta.value + "\n" + "连接断开!";
};
} else {
alert("浏览器不支持Websocket")
} function send(message) {
if (!window.WebSocket) {
return;
}
if (socket.readyState === WebSocket.OPEN) {
socket.send(message);
} else {
alert("连接未开启");
}
}
</script> <!--客户端访问后台 websocket程序-->
<form action="" onsubmit="return false;">
<textarea name="message" style="width: 400px;height: 200px;"></textarea> <input type="button" value="发送数据" onclick="send(this.form.message.value)"> <h3>服务器端输出:</h3>
<textarea id="responseText" style="width: 400px;height: 300px;"></textarea>
<input type="button" onclick="javascript:document.getElementById('responseText').value='';" value="清空内容">
</form>
</body>
</html>
Netty学习——通过websocket编程实现基于长连接的双攻的通信的更多相关文章
- 京东的Netty实践,京麦TCP网关长连接容器架构
背景 早期京麦搭建 HTTP 和 TCP 长连接功能主要用于消息通知的推送,并未应用于 API 网关.随着逐步对 NIO 的深入学习和对 Netty 框架的了解,以及对系统通信稳定能力越来越高的要求, ...
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...
- comet基于HTTP长连接技术(java即时通信,推送技术详解)
服务器推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息,服务器发送一批数据,浏览器显示消息,同时保证与服务器的连接,当服务器需要再一次的发送数据,浏览器显示数据并保持连接. comet基 ...
- 通过netty实现服务端与客户端的长连接通讯,及心跳检测。
基本思路:netty服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的key.每次服务器端如果要向某个客户端发送消息,只需根据ClientId取出对应的S ...
- python 之 网络编程(基于TCP协议的套接字通信操作)
第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...
- python socket 编程之三:长连接、短连接以及心跳
长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...
- Socket编程中的长连接、短链接以及心跳包机制详解
参考:http://blog.csdn.net/zdwzzu2006/article/details/7723738 一.定义 1.TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,se ...
- python socket 编程之三:长连接、短连接以及心跳(转药师Aric的文章)
长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...
- python 之 网络编程(基于UDP协议的套接字通信)
8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...
随机推荐
- 前端与算法 leetcode 350. 两个数组的交集 II
目录 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 概要 提示 解析 解法一:哈希表 解法二:双指针 解法三:暴力法 算法 # 前端与算法 leetcode 350. 两 ...
- 洛谷 pP2146 [NOI2015]软件包管理器
题目的传送门 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...
- mysql双主互为主从配置
在使用双主互为主从的模式前提是互为主从的两个数据库,表的主键必须是自增的. 环境不多说了 ,多台mysql单实例或单台多实例都可以.多实例的配置请参考:https://www.cnblogs.com/ ...
- Windows下编译最新版ChezScheme
据说ChezScheme是最快的神级编译器,一秒钟几百万行,王垠说的2秒内编译自身绝不是夸张(看这里<揭秘Chez Scheme>,Scheme中文社区).ChezScheme由美国印第安 ...
- C++中对C的扩展学习新增语法——引用
引用 引用的好处: 1.引用的好处 C++使用结构体,不需要再使用 typedef. 2.值传递是将实参进行拷贝,赋值给形参,如果对象比较大,每次拷贝效率比较低,并且函数内部无法修改外部变量的值,能力 ...
- 一分钟带你了解下Spring Security!
一.什么是Spring Security? Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,它是用于保护基于Spring的应用程序的实际标准. Spring Secu ...
- Mac上sonar插件的安装及使用
本文主要讲解sonar的安装及使用. 分为两个维度来讲解 1. 使用sonarqube以及自带的Derby数据库 2. 使用sonarqube以及配置mysql数据库 ---------------- ...
- PHP-会话控制Cookie和Session
会话控制:就是为了我们在访问页面和页面之间的跳转是,能够识别到你的登录状态,已经你的登录时长等 在php的会话控制当中,涉及到两个概念Cookie和Session Cookie 会话控制 原理:在登录 ...
- 无法优化的O(n!) 算法
旅行商问题: 有一位旅行商,他需要前往5个城市. 要前往这5个城市,同时要确保旅程最短. 对于每种顺序,他都计算总旅程,再挑选出旅程最短的路线.5个城市有120种不同的排列方式.因此,在涉及5个城市时 ...
- Openlayers Projection导致经纬度颠倒问题
问题: openlayers3调用TileWMS接口,实现Openlayers加载Geoserver转发的ArcGIS切片时,web墨卡托(wkid3857)没有问题,但是WGS84(wkid4326 ...