WebSocket协议可以实现前后端全双工通信,从而取代浪费资源的长轮询。在此协议的基础上,可以实现前后端数据、多端数据,真正的实时响应。在学习WebSocket的过程中,实现了一个简化版群聊,过程和代码详细记录在这篇文章中。

本篇文章来自董沅鑫的个人网站,引用、转载请指明出处

查看更多知识,或者技术交流:请访问godbmw.com

1 概述

1.1 WebSocket 是什么?

  1. 建立在 TCP 协议之上的网络通信协议
  2. 全双工通信协议
  3. 没有同源限制
  4. 可以发送文本、二进制数据等

1.2 为什么需要 WebSocket?

了解计算机网络协议的人,应该都知道:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。

这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息。

因此,如果在客户端想实时监听服务器变化,必须使用 ajax 来进行轮询,效率低,浪费资源。

而 websocket 就可以使得前后端进行全双工通信(两方都可以向对方进行数据推送),是真正的平等对话

2 WebSocket 客户端

支持HTML5的浏览器支持 WebSocket 协议:

var ws = new WebSocket(url); // 创建一个websocket对象

2.1 WebSocket 属性

属性 描述
ws.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
ws.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

2.2 WebSocket 方法

属性 描述
ws.send() 数据发送
ws.close() 关闭连接

2.3 Websocket 事件

属性 描述
open 连接建立触发
message 通信时触发
error 出错触发
close 关闭连接触发

2.4 代码实现

假设我们在本地8080端口打开了websocket服务,那么,下面代码可以在浏览器中实现和这个服务的通信:

<body>
<script>
var ws = new WebSocket("ws://localhost:8080/");
// 建立连接触发
ws.onopen = function () {
ws.send("open ws");
console.log("open ws");
}; // 接收服务端数据触发
ws.onmessage = function (evt) {
var data = evt.data;
console.log("Data is ", data);
}; // 断开连接触发
ws.onclose = function () {
console.log("close ws");
};
</script>
</body>

3 WebSocket 服务端

关于服务端实现,根据技术选型不同,可以选用不同的库和包。我这里使用的是nodews库来websocket服务端。

阮一峰的博文提到的socket.io库,在浏览器端的写法不兼容原生API,准确来说,它们自己实现了一套websocket。所以,使用的时候前后端都应该引用第三方库。这样就造成了代码迁移性,严重下降。

综上所述,ws库有以下优点:

  1. 兼容性好,兼容浏览器原生API
  2. 长期维护,效果稳定
  3. 使用方便(往下看就知道了)

4 实现群聊

4.1 群聊 服务端实现

首先,在命令行中,安装ws库: npm install ws --save

现在,利用ws来实现一个监听8080端口的websocket服务器,讲解都在代码注释里,一目了然

const PORT = 8080; // 监听端口
const WebSocket = require("ws"); // 引入 ws 库 const wss = new WebSocket.Server({ port: PORT }); // 声明wss对象 /**
* 向除了本身之外所有客户端发送消息,实现群聊功能
* @param {*} data 要发送的数据
* @param {*} ws 客户端连接对象
*/
wss.broadcastToElse = function broadcast(data, ws) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}; /* 客户端接入,触发 connection */
wss.on("connection", function connection(ws, req) {
let ip = req.connection.remoteAddress; // 通过req对象可以获得客户端信息,比如:ip,headers等 /* 客户端发送消息,触发 message */
ws.on("message", function incoming(message) {
ws.send(message); // 向客户端发送消息
wss.broadcastToElse(message, ws); // 向 其他的 客户端发送消息,实现群聊效果
}); });

4.2 群聊 客户端实现

为了方便编写,这里引入了jquerybootstrap这两个库,只需要关注js代码即可。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>群聊</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/jquery/3.3.0/jquery.min.js"></script>
</head>
<body>
<div class="container">
<textarea class="form-control" rows="30" disabled="disabled" id="show-area"></textarea>
<input type="text" class="form-control" placeholder="请输入聊天内容" id="chat-input">
<button type="button" class="btn btn-info" id="send-btn">发送</button>
</div>
<script>
var userName = parseInt(Math.random() * 1000, 10) // 随机用户名, 以标识身份 var sendBtn = $("#send-btn"), // 发送信息按钮
chatInput = $("#chat-input"), // 聊天信息输入框
showArea = $("#show-area") // 聊天信息展示框 var ws = new WebSocket("ws://localhost:8080/") // 初始化WebSocket对象 sendBtn.on("click", function () {
var content = chatInput.val()
if (content.length === 0) {
return alert("请不要输入空白内容")
}
content = "At " + (new Date()).toString() + "\n" + "来自用户" + userName + "\n" + content // 拼接用户信息、时间信息和消息
ws.send(content) // 发送消息
chatInput.val("") // 清空输入框
}) ws.onopen = function () { console.log("Conncet open") }
ws.onmessage = function (evt) {
var data = evt.data
showArea.val(showArea.val() + data + "\n\n") // 刷新聊天信息展示框:显示群聊信息
}
ws.onclose = function () { console.log("Connect close") }
</script>
</body>
</html>

4.3 群聊 效果展示

首先启动我们的服务端代码:node server.js 。其中,server.js是放置服务端代码的文件。

然后,我们打开2次编写的html代码,这相当于,打开2个客户端。来检测群聊功能。

5. 相关资料

本篇文章来自董沅鑫的个人网站,引用、转载请指明出处

查看更多知识,或者技术交流:请访问godbmw

websocket学习和群聊实现的更多相关文章

  1. 【Java分享客栈】SpringBoot整合WebSocket+Stomp搭建群聊项目

    前言 前两周经常有大学生小伙伴私信给我,问我可否有偿提供毕设帮助,我说暂时没有这个打算,因为工作实在太忙,现阶段无法投入到这样的领域内,其中有两个小伙伴又问到我websocket该怎么使用,想给自己的 ...

  2. WebSocket 实现链接 群聊(low low low 版本)

    py 文件: """ 下载 gevent-websocket 0.10.1 基于Flask + geventWebSocket 建立连接,发送消息,实现群消息功能. &q ...

  3. 基于websocket搭建简易群聊

    1.前端HTML <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&qu ...

  4. 一例完整的websocket实现群聊demo

    前言 业余我都会花一些时间在tcp.http和websocket等领域的学习,现在觉得有点收获,所以把一个基于websocket的群聊功能的例子提供给大家玩玩.当然这是一个很完整的例子,包括webso ...

  5. websocket(二)--简单实现网页版群聊

    websocket可以实现服务端的消息推送,而不必在客户端轮询,大大的节省的资源,对于实时通讯来说简直是个大喜讯. 在上一篇文章中介绍了协议握手,这篇文章将通过实现简单的群聊来帮助进一步了解webso ...

  6. WebSocket刨根问底(三)之群聊

    前两篇文章[WebSocket刨根问底(一)][WebSocket刨根问底(二)]我们介绍了WebSocket的一些基本理论,以及一个简单的案例,那么今天继续,我们来看一个简单的群聊的案例,来进一步了 ...

  7. flask 第五章 WebSocket GeventWebsocket 单聊群聊 握手 解密 加密

    1.WebSocket 首先我们来回顾一下,我们之前用socket学习过的项目有: 1.django 2.flask 3.FTP - 文件服务 HTTP - TCP (特点): 1.一次请求,一次响应 ...

  8. websocket实现群聊和单聊(转)

    昨日内容回顾 1.Flask路由 1.endpoint="user" # 反向url地址 2.url_address = url_for("user") 3.m ...

  9. WebSocket群聊与单聊

    一 . WebSocket实现群聊 py文件代码 # py文件 from flask import Flask, render_template, request from geventwebsock ...

随机推荐

  1. 简单好用的时间选择插件My97datepicker

    我们经常会需要验证字符串的格式,比如密码长度范围.电子邮件格式.固定电话号码和手机号码格式等,这个时候我们经常会需要用到正则表达式.但是正则表达式用起来性能会低一点,所以在需要验证的时候能不使用正则表 ...

  2. zookeeper配置文件共享中心

    最近频繁的系统上线,每次打包都要把配置文件替换为正式环境的配置文件,虽然说就是复制粘贴的事,架不住文件杂乱,而且多. 期初的想法是有没有办法将配置文件与系统隔离开来,这样在更新时候,就只需要更新代码部 ...

  3. 在Ubuntu登陆界面输入密码之后,黑屏一闪后,又跳转到登录界面

    现象:在Ubuntu登陆界面输入密码之后,黑屏一闪后,又跳转到登录界面.原因:主目录下的.Xauthority文件拥有者变成了root,从而以用户登陆的时候无法都取.Xauthority文件.说明:X ...

  4. SQL Server表分区(水平分区及垂直分区)

    什么是表分区? 表分区分为水平表分区和垂直表分区,水平表分区就是将一个具有大量数据的表,进行拆分为具有相同表结构的若干个表:而垂直表分区就是把一个拥有多个字段的表,根据需要进行拆分列,然后根据某一个字 ...

  5. MongoDB 数据库

    数据库: 关系型数据库       mysql           收费        速度快     字段类型 非关系型数据库   MongoDB    不收费    速度慢一些 存储数据都是字符串 ...

  6. Java学习笔记45(多线程二:安全问题以及解决原理)

    线程安全问题以及解决原理: 多个线程用一个共享数据时候出现安全问题 一个经典案例: 电影院卖票,共有100座位,最多卖100张票,买票方式有多种,网上购买.自主售票机.排队购买 三种方式操作同一个共享 ...

  7. 搭建docker环境准备

    Docker平台的基本构成

  8. IDEA 图标介绍。 缓存和索引介绍、清理方法和Debug使用

    一.图标 二.缓存和索引 IntelliJ IDEA 的缓存和索引主要是用来加快文件查询,从而加快各种查找.代码提示等操作的速(上图中的图标能这样显示也是靠索引).某些特殊条件下,IntelliJ I ...

  9. Linux下安装配置与使用MySQL数据库

    Linux下安装配置与使用MySQL数据库 在Linux下安装做开发时往往少不了要使用到MySQL数据库,下面就Linux系统为例讲解一下,如何安装MySQL数据库,如何启用/停.止MySQL服务,如 ...

  10. opus代码解析

    opus的初始化函数如下所示,在初始化的过程中,从代码结构上来看,这里主要完成是内存的申请,基本参数的定义 cOpusEncoder *opus_encoder_create(opus_int32 F ...