WebSocket+Netty构建web聊天程序(一)

简介: WebSocket+Netty构建web聊天程序(一)

WebSocket#


传统的浏览器和服务器之间的交互模式是基于请求/响应的模式,虽然可以使用js发送定时任务让浏览器在服务器中拉取但是弊端很明显,首先就是不能避免的延迟,其次就是频繁的请求,让服务器的压力骤然提升


WebSocket是H5新增的协议,用于构建浏览器和服务器之间的不受限的长连接的通信模式,不再局限于请求/响应式的模型,服务端可以主动推送消息给客户端,(游戏有某个玩家得奖了的弹幕)基于这个特性我们可以构建我们的实时的通信程序


协议详情:#


websocket建立连接时,是通过浏览器发送的HTTP请求,报文如下:


GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13


  • 首先GET请求是以 ws开头的
  • 其中请求头中的Upgrade: websocket Connection: Upgrade表示尝试建立WebSocket连接


对于服务端的相应数据


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string


其中的101,表示服务端支持WebSocket协议, 双方基于Http请求,成功建立起WebSocket连接,双方之间的通信也不再通过HTTP


JS对WebSocket的封装对象#


对于JS的WebSocket对象来说,它常用 4个回调方法,以及两个主动方法


方法名 作用
onopen() 和服务端成功建立连接后回调
onmessage(e) 收到服务端的的消息后回调,e为消息对象
onerror() 链接出现异常回调,如服务端关闭
onclose() 客户端单方面断开连接时回调
send(e) 主动向服务端推送消息
close() 主动关闭通道


再次对WebSocket进行封装#


知道了回调函数回调时机,我们接下来要做的就是在他的整个生命周期的不同回调函数中,添加我们指定的动作就ok了,下面是通过Window定义一个全局的聊天对象CHAT


window.CHAT={
var socket = null;
// 初始化socket
init:function(){
// 判断当前的浏览器是否支持WebSocket
if(window.WebSocket){
  // 检验当前的webSocket是否存在,以及连接的状态,如已经连接,直接返回
  if(CHAT.socket!=null&&CHAT.socket!=undefined&&CHAT.socket.readyState==WebSocket.OPEN){
    return false;
  }else{// 实例化 , 第二个ws是我们可以自定义的, 根据后端的路由来
    CHAT.socket=new WebSocket("ws://192.168.43.10:9999/ws");
    // 初始化WebSocket原生的方法
    CHAT.socket.onopen=CHAT.myopen();
    CHAT.socket.onmessage=CHAT.mymessage();
    CHAT.socket.onerror=CHAT.myerror();
    CHAT.socket.onclose=CHAT.myclose(); 
  }
}else{
  alert("当前设备不支持WebSocket");
}
}
// 发送聊天消息
chat:function(msg){
  // 如果的当前的WebSocket是连接的状态,直接发送 否则从新连接
  if(CHAT.socket.readyState==WebSocket.OPEN&&CHAT.socket!=null&&CHAT.socket!=undefined){
    socket.send(msg);
  }else{
    // 重新连接
    CHAT.init();
    // 延迟一会,从新发送
    setTimeout(1000);
    CHAT.send(msg);
  }
}
// 当连接建立完成后对调
myopen:function(){
  // 拉取连接建立之前的未签收的消息记录
  // 发送心跳包
}
mymessage:function(msg){
  // 因为服务端可以主动的推送消息,我们提前定义和后端统一msg的类型, 如,拉取好友信息的消息,或 聊天的消息
  if(msg==聊天内容){
  // 发送请求签收消息,改变请求的状态
  // 将消息缓存到本地
  // 将msg 转换成消息对象, 植入html进行渲染
  }else if(msg==拉取好友列表){
  // 发送请求更新好友列表
  }
}
myerror:function(){
  console.log("连接出现异常...");
}
myclose:function(){
  console.log("连接关闭...");
}
keepalive: function() {
  // 构建对象
  var dataContent = new app.DataContent(app.KEEPALIVE, null, null);
  // 发送心跳
  CHAT.chat(JSON.stringify(dataContent));
  // 定时执行函数, 其他操作
    // 拉取未读消息
    // 拉取好友信息
}
}


对消息类型的约定#


WebSocket对象通过send(msg);方法向后端提交数据,常见的数据如下:

  • 客户端发送聊天消息
  • 客户端签收消息
  • 客户端发送心跳包
  • 客户端请求建立连接


为了使后端接收到不同的类型的数据做出不同的动作, 于是我们约定发送的msg的类型;


// 消息action的枚举,这个枚举和后端约定好,统一值
CONNECT: 1,   // 第一次(或重连)初始化连接
CHAT: 2,    // 聊天消息
SIGNED: 3,    // 消息签收
KEEPALIVE: 4,   // 客户端保持心跳
PULL_FRIEND:5,  // 重新拉取好友
// 消息模型的构造函数
ChatMsg: function(senderId, receiverId, msg, msgId){
  this.senderId = senderId;
  this.receiverId = receiverId;
  this.msg = msg;
  this.msgId = msgId;
}
//  进一步封装两个得到最终版消息模型的构造函数
DataContent: function(action, chatMsg, extand){
  this.action = action;
  this.chatMsg = chatMsg;
  this.extand = extand;
}


如何发送数据?#


我们使用js,给发送按钮绑定点击事件,一经触发,从缓存中获取出我们需要的参数,调用


CHAT.chat(Json.stringify(dataContent));


后端netty会解析dataContent的类型,进一步处理


如何签收未与服务器连接时好友发送的消息?#


  • 消息的签收时机:
    之所以会有未签收的信息,是因为客户端未与服务端建立WebSocket连接, 当服务端判断他维护的channel组中没有接受者的channel时,不会发送数据,而是把数据持久化到数据库,并且标记flag=未读, 所以我们签收信息自然放在客户端和服务端建立起连接时的回调函数中执行
  • 步骤:
  • 客户端通过js请求,拉取全部的和自己相关的flag=未读的消息实体列表
  • 从回调函数数中,把列表中的数据取出,缓存在本地
  • 将列表中的数据回显在html页面中
  • 和后端约定,将该列表中所有的实例的id取出,用逗号分隔拼接成字符串, 以action=SIGNED的方式发送给后端,让其进行签收


相关文章
|
15天前
|
存储 JavaScript 前端开发
webSocket+Node+Js实现在线聊天(包含所有代码)
文章介绍了如何使用WebSocket、Node.js和JavaScript实现在线聊天功能,包括完整的前端和后端代码示例。
65 0
|
1天前
|
前端开发 网络协议
netty整合websocket(完美教程)
本文是一篇完整的Netty整合WebSocket的教程,介绍了WebSocket的基本概念、使用Netty构建WebSocket服务器的步骤和代码示例,以及如何创建前端WebSocket客户端进行通信的示例。
9 2
netty整合websocket(完美教程)
|
1天前
|
SQL 安全 测试技术
漏洞扫描技术:对Web应用程序进行漏洞扫描
漏洞扫描技术:对Web应用程序进行漏洞扫描
10 1
|
2天前
|
Rust 网络协议 应用服务中间件
granian:让你的 Web 应用程序快如闪电
granian:让你的 Web 应用程序快如闪电
18 2
|
12天前
|
网络协议 JavaScript API
深入浅出 WebSocket:实现实时 web 通信
在现代Web应用中,实时通信至关重要。WebSocket通过单个TCP连接实现全双工通信,允许服务器主动向客户端发送消息。本文介绍了WebSocket的核心概念、实现方法及其优势。WebSocket建立了持久连接,支持实时数据传输,减少服务器负载,并提供双向通信。通过JavaScript API可轻松建立连接、发送接收消息及处理异常。使用WebSocket,开发者能构建更动态的Web应用。
|
15天前
|
JavaScript 前端开发 UED
WebSocket在Python Web开发中的革新应用:解锁实时通信的新可能
在快速发展的Web应用领域中,实时通信已成为许多现代应用不可或缺的功能。传统的HTTP请求/响应模式在处理实时数据时显得力不从心,而WebSocket技术的出现,为Python Web开发带来了革命性的变化,它允许服务器与客户端之间建立持久的连接,从而实现了数据的即时传输与交换。本文将通过问题解答的形式,深入探讨WebSocket在Python Web开发中的革新应用及其实现方法。
28 3
|
1天前
|
安全 Java Linux
Kali渗透测试:通过Web应用程序实现远程控制
Kali渗透测试:通过Web应用程序实现远程控制
24 0
|
1天前
|
存储 缓存 安全
如何使用 PHP 将天气跟踪集成到 Web 应用程序中
如何使用 PHP 将天气跟踪集成到 Web 应用程序中
9 0
|
前端开发 Java
Netty In Action中文版 - 第二章:第一个Netty程序
Netty In Action中文版 - 第二章第一个Netty程序 本章介绍 获取Netty4最新版本 设置运行环境来构建和运行netty程序 创建一个基于Netty的服务器和客户端 拦截和处理异常 编写和运行Netty服务器和客户端 本章将简单介绍Netty的核心概念这个狠心概念就是学习Netty是如何拦截和处理异常对于刚开始学习netty的读者利用netty的异常拦截机制来调试程序问题很有帮助。
1566 0
|
存储 缓存 NoSQL
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)
本文将要分享的是如何从零实现一套基于Netty框架的分布式高可用IM系统,它将支持长连接网关管理、单聊、群聊、聊天记录查询、离线消息存储、消息推送、心跳、分布式唯一ID、红包、消息同步等功能,并且还支持集群部署。
13449 1