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 缺点:不可靠:发送数据,无需 ...
随机推荐
- NOIP模拟 30
补坑,很多都忘了. T1 树 像我这种人都能考场A掉当然是道水题辣 求出每条有向边的期望就好了 T2 回文串 当时毫无思路,暴力写挂. 首先把B转过来,那么都变成后缀的前缀拼起来 对于每一个LCP,他 ...
- Vue使用antV G2制作看板
工作中需要制作一个看板,选型选用antV G2进行开发. 由于项目前端是使用Vue,于是研究了antVG2在Vue中的使用. 1.安装antv/g2 npm install @antv/g2 --sa ...
- 机器学习之scikit-learn库
前面讲到了,这个库适合学习,轻量级,所以先学它. 安装就不讲了,简单.不过得先安装numpy和pandas库才能安装scikit-learn库. 如果安装了anaconda得话,会自带有这个库. -- ...
- 你知道MySQL中的主从延迟吗?
前言 在一个MySQL主备关系中,每个备库接受主库的binlog并执行. 正常情况下,只要主库执行更新生成所有的binlog,都可以传到备库并被正常的执行,这样备库就能够达到跟主库一样的状态,这就是最 ...
- javascript关于box2djs和matterjs之间的选择
javascript关于box2djs和matterjs之间的选择box2djs资料少很多时候需要看c++版本资料 然后转化成js 还有转化成像素坐标不准确 matterjs文档丰富 上手容易 建议用 ...
- HTML创建图像映射,布局,表单
来源: 实验楼 创建图像映射 在这之前我们动手试验过将图片作为链接来使用,触发链接的方式就是点击图片的任何地方都可以链接到跳转地址,有时我们需要实现,点击图片的不同地方跳转到不同的地方.意思就是,一张 ...
- C语言I博客作业08
这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 作业 我在这个课程的目标是 熟悉使用while和do-while结构解决问题 这个作业在那个具体方面帮助我实现目标 pta题目及查找的资料 ...
- C语言:大数取余
大数取余数(数组) 今天做学校的oj时遇到一题,问题可见一下截图: 查遍各大论坛,都没有遇到合适的方法,普通方法不可用,要采用数组的形式. 被除数超过long long类型,不能采用常规思路,否则会出 ...
- 基于R数据分析之常用Package讲解系列--1. data.table
利用data.table包变形数据 一. 基础概念 data.table 这种数据结构相较于R中本源的data.frame 在数据处理上有运算速度更快,内存运用更高效,可认为它是data.frame ...
- 领扣(LeetCode)独特的电子邮箱地址 个人题解
每封电子邮件都由一个本地名称和一个域名组成,以 @ 符号分隔. 例如,在 alice@leetcode.com中, alice 是本地名称,而 leetcode.com 是域名. 除了小写字母,这些电 ...