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编程实现基于长连接的双攻的通信的更多相关文章

  1. 京东的Netty实践,京麦TCP网关长连接容器架构

    背景 早期京麦搭建 HTTP 和 TCP 长连接功能主要用于消息通知的推送,并未应用于 API 网关.随着逐步对 NIO 的深入学习和对 Netty 框架的了解,以及对系统通信稳定能力越来越高的要求, ...

  2. 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室

    实现网页版的在线聊天室的方法有很多,在没有来到HTML5之前,常见的有:定时轮询.长连接+长轮询.基于第三方插件(如FLASH的Socket),而如果是HTML5,则比较简单,可以直接使用WebSoc ...

  3. comet基于HTTP长连接技术(java即时通信,推送技术详解)

    服务器推送技术的基础思想是将浏览器主动查询信息改为服务器主动发送信息,服务器发送一批数据,浏览器显示消息,同时保证与服务器的连接,当服务器需要再一次的发送数据,浏览器显示数据并保持连接. comet基 ...

  4. 通过netty实现服务端与客户端的长连接通讯,及心跳检测。

    基本思路:netty服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的key.每次服务器端如果要向某个客户端发送消息,只需根据ClientId取出对应的S ...

  5. python 之 网络编程(基于TCP协议的套接字通信操作)

    第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...

  6. python socket 编程之三:长连接、短连接以及心跳

    长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...

  7. Socket编程中的长连接、短链接以及心跳包机制详解

    参考:http://blog.csdn.net/zdwzzu2006/article/details/7723738 一.定义 1.TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,se ...

  8. python socket 编程之三:长连接、短连接以及心跳(转药师Aric的文章)

    长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...

  9. python 之 网络编程(基于UDP协议的套接字通信)

    8.5 基于UDP协议的套接字通信 UDP协议:数据报协议 特点:无连接,一发对应一收,先启动哪一端都不会报错 优点:发送效率高,但有效传输的数据量最多为500bytes 缺点:不可靠:发送数据,无需 ...

随机推荐

  1. 0818NOIP模拟测试25——B卷简记

    幸亏考场上没考这个,T1结论T2不会T3板子.估计会死的更惨 T1是学长讲过的Cat变式,沿直线y=x+1翻折方案数相减,现推,15分钟弄出来没什么问题. 只要不要把m,n读反就行. T3是个tarj ...

  2. Intellij IDEA配置JDK、Maven和Tomcat

    一.配置JDK 1.File-->Project Structure 2.选择SDKs 3.点击+号添加自己本地jdk的安装目录,保存即可 二.配置Maven 1.File -> Othe ...

  3. 迁移桌面程序到MS Store(11)——应用SVG图标

    在传统桌面程序中,对图标的使用大多是直接嵌入JPG或者PNG的图片.在祖传的1366x768分辨率下,并没有什么问题.相对于手机硬件的突飞猛进,也侧面反映了PC行业的落寞和桌面程序开发的不思进取.用3 ...

  4. Machine Learning in Action ---- kNN

    ------------恢复内容开始------------ # -*- coding: utf-8 -*- """ Created on Thu Nov 14 19:2 ...

  5. 前端小白在asp.net core mvc中使用ECharts

    对于在浏览器中绘制图形图表,目前有较多的js类库可以使用,如:ChartJS,Flot,canvasjs等,但是今天介绍的主角为国产图表库,并在apache孵化,就是大名鼎鼎的echarts. 前方高 ...

  6. celery 启用worker ValueError: not enough values to unpack

    [2018-01-12 19:08:15,545: INFO/MainProcess] Received task: tasks.add[5d387722-5389-441b-9b01-a619b93 ...

  7. 领扣(LeetCode)移动零 个人题解

    给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作, ...

  8. 系统信息命令(uname、dmesg、df、hostname、free)

    uname 显示计算机及操作系统相关的信息,uname -a显示全部信息,uname -r内核的发行号,各种信息可以有单独的选项分别指出 [lixn@Fedora24 ~]$ uname -a Lin ...

  9. linux内核的preempt抢占调度,preempt_count抢占保护“锁”

    抢断调度,是调度机制对实时系统需要的支持,是一种快速响应的重调度机制.既然与重调度有关,那么就先回顾一下调度和重调度. 调度分两种情况,1. 一种是自愿调度,由代码主动调用schedule来让度cpu ...

  10. windows 10上源码编译dlib教程 | compile dlib on windows 10

    本文首发于个人博客https://kezunlin.me/post/654a6d04/,欢迎阅读! compile dlib on windows 10 Series Part 1: compile ...