Netty之实现WebSocket用户单聊....
简单介绍一下webSocket:
我们一直使用的http协议只能由客户端发起,服务端无法直接进行推送,这就导致了如果服务端有持续的变化客户端想要获知就比较麻烦。WebSocket协议就是为了解决这个问题应运而生。WebSocket协议,客户端和服务端都可以主动的推送消息,可以是文本也可以是二进制数据。而且没有同源策略的限制,不存在跨域问题。协议的标识符就是ws。
WebSocket是H5之后提供的一种网络通讯技术,属于应用层协议。它基于 TCP 传输协议,并复用 HTTP 的握手通道。
WebSocket帧:
数据帧: ---用来传递数据
TextWebSocketFrame:文本帧
BinaryWebSocketFrame:二进制帧 (传输的图片、表情等等)
状态帧: ---检测心跳
PingWebSocketFrame:ping帧(客户端发送ping帧)
PongWebSocketFrame:pong帧(服务端响应pong帧)
CloseWebSocketFrame:关闭帧
开始通讯:::::
依赖这些省略........
服务端
/**
* @Author Joker
* @Date 2020/11/16
* @since 1.8
*/
@Slf4j
public class ServerDemo {
public static void main(String[] args) {
EventLoopGroup masterEventLoopGroup = new NioEventLoopGroup();
EventLoopGroup slaveEventLoopGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
ChannelFuture channelFuture = bootstrap.group(masterEventLoopGroup, slaveEventLoopGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(1024 * 1024));
pipeline.addLast(new WebSocketServerProtocolHandler("/"));
// 在10秒之内收不到消息自动断开
pipeline.addLast(new ReadTimeoutHandler(10, TimeUnit.SECONDS));
pipeline.addLast(new WebSocketHandler());
}
})
.bind(8888);
try {
channelFuture.sync();
System.out.println("连接服务器成功...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
消息处理:
/**
* @Author Joker
* @Date 2020/11/16
* @since 1.8
*/
@Slf4j
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
private final String HEART = "ws-heart";
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
String text = textWebSocketFrame.text();
System.out.println("接收到消息: " + text);
// 判断接收内容是否为心跳值
if(HEART.equals(text)){
TextWebSocketFrame socketFrame = new TextWebSocketFrame(HEART);
channelHandlerContext.writeAndFlush(socketFrame);
}
}
/**
* 用户加入
* @param ctx
* @throws Exception
*/
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
super.channelRegistered(ctx);
System.out.println("用户连接");
}
/**
* 用户断开
* @param ctx
* @throws Exception
*/
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
super.channelUnregistered(ctx);
System.out.println("用户断开");
}
/**
*
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
System.out.println("用户非正常断开");
}
}
前端HTML页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>websocket</title>
<script src="./js/jquery-3.4.1.js" type="text/javascript" charset="UTF-8"></script>
</head>
<script>
$(function(){
var ws = new WebSocket("ws://127.0.0.1:8888");
var heartTime;
if(window.WebSocket){
// 连接服务器
ws.onopen = function(){
debugger
var html = "<span style='color:green'>连接服务器成功</span></br>";
$("#toke").append(html);
// 连接成功后发送心跳
sendHeart();
}
// 断开服务器
ws.onclose = function(e){
clearInterval(heartTime);
var html = "<span style='color:red'>客户端断开连接</span></br>"
$("#toke").append(html);
}
// 服务器发生异常
ws.onerror = function(){
var html = "<span style='color:red'>服务器异常</span></br>"
$("#toke").append(html);
}
ws.onmessage = function(data){
// 判断服务端返回的值是否为心跳返回值
if(data.data == "ws-heart"){
return;
}
var html = "<span>服务器:"+ data.data +"</span></br>"
$("#toke").append(html);
}
} else{
alert("当前浏览器不支持WebSocket!");
}
$("#send").click(function(){
var msg = $("#con").val();
ws.send(msg);
msg = "<span style='color:blue;display:block;text-align:right;margin-right:5px'>"+ msg +"</span></br>";
var showMsg = $("#toke");
showMsg.append(msg);
$("#con").val("");
});
function sendHeart(){
heartTime = setInterval(function(){
ws.send("ws-heart");
},5000);
}
})
</script>
<body>
<div id="toke" style="width: 400px; height: 300px;border: 1px solid #f00;">
</div>
<input type="text" name="con" id="con" width="100px" />
<button id="send">发送</button>
</body>
</html>
三合一,这就是一个简单的webSocket
演示结果::::