SocketIo的使用和基于SocketIO的聊天室

  Socket.IO 是一个库,可以在客户端和服务器之间实现 低延迟, 双向 和 基于事件的 通信。

一、Socket.IO的特点

以下是 Socket.IO 在普通 WebSockets 上提供的功能:

1、HTTP 长轮询回退

如果无法建立 WebSocket 连接,连接将回退到 HTTP 长轮询。
这个特性是人们在十多年前创建项目时使用 Socket.IO 的原因(!),因为浏览器对 WebSockets 的支持仍处于起步阶段。
即使现在大多数浏览器都支持 WebSockets(超过97%),它仍然是一个很棒的功能,因为我们仍然会收到来自用户的报告,这些用户无法建立 WebSocket 连接,因为他们使用了一些错误配置的代理。

2、自动重新连接

在某些特定情况下,服务器和客户端之间的 WebSocket 连接可能会中断,而双方都不知道链接的断开状态。
这就是为什么 Socket.IO 包含一个心跳机制,它会定期检查连接的状态。
当客户端最终断开连接时,它会以指数回退延迟自动重新连接,以免使服务器不堪重负。

3、数据包缓冲

当客户端断开连接时,数据包会自动缓冲,并在重新连接时发送。

4、收到后的回调

Socket.IO 提供了一种方便的方式来发送事件和接收响应

5、广播

在服务器端,您可以向所有连接的客户端或客户端的子集发送事件

6、多路复用

命名空间允许您在单个共享连接上拆分应用程序的逻辑。例如,如果您想创建一个只有授权用户才能加入的“管理员”频道

更多信息请访问socketIO的介绍文档

二、Socket.IO发送消息常见的方式

  socket.io用on函数给调用的时间注册调用函数,用emit函数来发送时间,以此来时间客户端和服务器两端的通信,常用的使用方式如下:

1、只发送事件

发送端代码:

socket.emit('action');

表示发送了一个action命令,命令是字符串的,在另一端接收时,可以这么写:

socket.on('action',function(){...
});

2、发送事件和一个数据

发送端:

socket.emit('action',data);

表示发送了一个action命令,还有data数据,在另一端接收时,可以这么写:

socket.on('action',function(data){...
});

3、发送事件和多个数据

发送端:

socket.emit('action',arg1,arg2);

表示发送了一个action命令,还有两个数据,在另一端接收时,可以这么写:

socket.on('action',function(arg1,arg2){...
});

如果是多个参数,就在后面加参数就行了

4、发送事件和数据及回调函数

在emit方法中包含回调函数,例如:

socket.emit('action',data, function(arg1,arg2){...
} );

那么这里面有一个回调函数可以在另一端调用,另一端可以这么写:

socket.on('action',function(data,fn){ ...fn('a','b');...});

三、emit发送消息的范围

下面是emit不同方法发送消息的范围:

  // 只发给sender。 sending to the clientsocket.emit('hello', 'can you hear me?', 1, 2, 'abc');// 发给所有人,除了sender。 sending to all clients except sendersocket.broadcast.emit('broadcast', 'hello friends!');// 发给game房间所有人,除了sender。 sending to all clients in 'game' room except sendersocket.to('game').emit('nice game', "let's play a game");// 发给game1和/或game2所有人,除了sender。 sending to all clients in 'game1' and/or in 'game2' room, except sendersocket.to('game1').to('game2').emit('nice game', "let's play a game (too)");// 发给game房间所有人,包含sender。 sending to all clients in 'game' room, including senderio.in('game').emit('big-announcement', 'the game will start soon');// 发给域名myNamespacs所有人,包含sender。 sending to all clients in namespace 'myNamespace', including senderio.of('myNamespace').emit('bigger-announcement', 'the tournament will start soon');// 发给域名myNamespace里room房间的所有人,包含sender。 sending to a specific room in a specific namespace, including senderio.of('myNamespace').to('room').emit('event', 'message');// 发给某一个人 sending to individual socketid (private message)io.to(`${socketId}`).emit('hey', 'I just met you');

四、聊天室实现

1、项目结构

在这里插入图片描述

2、server.js

server.js实现了一个web服务器,主要的功能有两个

  • 实现一个nodejs的服务器,让浏览器能够加载到聊天网页
  • 用socket.io实现服务端接受客户连接和发送消息的功能
    其代码如下:
'use strict'// 配置日志
const log4j = require('log4js');
const logger = log4j.getLogger();// 配置http服务器
const {createServer} = require('http');
const express = require('express');
const serveIndex = require('serve-index');const app = express();
// 配置静态文件,位置不能乱
app.use(serveIndex('./public'));
app.use(express.static('./public'));// 创建http服务器
const http_server = createServer(app);// 配置socket io
const {Server} = require("socket.io");
// 让socketIo监听https服务器const io = new Server(http_server);// 配置socket发送消息逻辑
io.on('connection', (socket) => {logger.info('socket connection : ', socket);//socket.emit('joined',room,socket.id);只给当前用户发送//socket.to(room).emit('joined', room, socket.id);//除自己之外//io.in(room).emit('joined', room, socket.id)//房间内所有人//socket.broadcast.emit('joined', room, socket.id);//除自己,全部站点// 加入房间的处理逻辑socket.on('join', (room, userName) => {logger.info(`user join in. userName=${userName},room=${room}`);// socket加入room中socket.join(room);// 发送给当前用户用户加入成功socket.emit('joined', room, socket.id);});// 离开房间的处理逻辑socket.on('leave', (room, userName) => {logger.info(`user leave. userName=${userName},room=${room}`);socket.leave(room);socket.emit('leaved', room, socket.id);})// 发送消息逻辑socket.on('message', (room, data) => {// 给房间内的所有人发送消息(包括自己)io.in(room).emit('message', data);//不给自己发,只给别人发(前端需要适配自己发送的内容到消息显示框)//socket.to(room).emit('message', data);})});//启动服务器
http_server.listen(80);

3、index.html

index.html是聊天的网页,代码如下:

<html>
<head><title>Chat room</title><link rel="stylesheet" href="./css/main.css">
</head><body>
<table align="center"><tr><td><label>UserName:</label><input type="text" id="userName"></td></tr><tr><td><label>Room:</label><input type="text" id="room"><button id="connect">Connect</button><button id="leave">Leave</button></td></tr><tr><td><label>Content: </label><br><textarea disabled style="line-height: 1.5;" id="content" rows="10" cols="100"></textarea></td></tr><tr><td><label>Input: </label><br><textarea disabled id="input" rows="3" cols="100"></textarea></td></tr><tr><td><button disabled id="send">Send</button></td></tr>
</table><script src="/socket.io/socket.io.js"></script>
<script src="./js/client.js"></script>
</body></html>

4、main.css

main.css是index.html的布局格式文件,代码如下:

/**  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.**  Use of this source code is governed by a BSD-style license*  that can be found in the LICENSE file in the root of the source*  tree.*/
button {margin: 0 20px 25px 0;vertical-align: top;width: 134px;
}div#getUserMedia {padding: 0 0 8px 0;
}div.input {display: inline-block;margin: 0 4px 0 0;vertical-align: top;width: 310px;
}div.input > div {margin: 0 0 20px 0;vertical-align: top;
}div.output {background-color: #eee;display: inline-block;font-family: 'Inconsolata', 'Courier New', monospace;font-size: 0.9em;padding: 10px 10px 10px 25px;position: relative;top: 10px;white-space: pre;width: 270px;
}section#statistics div {display: inline-block;font-family: 'Inconsolata', 'Courier New', monospace;vertical-align: top;width: 308px;
}section#statistics div#senderStats {margin: 0 20px 0 0;
}section#constraints > div {margin: 0 0 20px 0;
}section#video > div {display: inline-block;margin: 0 20px 0 0;vertical-align: top;width: calc(50% - 22px);
}section#video > div div {font-size: 0.9em;margin: 0 0 0.5em 0;width: 320px;
}h2 {margin: 0 0 1em 0;
}section#constraints label {display: inline-block;width: 156px;
}section {margin: 0 0 20px 0;padding: 0 0 15px 0;
}section#video {width: calc(100% + 20px);
}video {--width: 90%;display: inline-block;width: var(--width);height: calc(var(--width) * 0.75);margin: 0 0 10px 0;
}@media screen and (max-width: 720px) {button {font-weight: 500;height: 56px;line-height: 1.3em;width: 90px;}div#getUserMedia {padding: 0 0 40px 0;}section#statistics div {width: calc(50% - 14px);}video {display: inline-block;width: var(--width);height: 96px;}
}

5、client.js

client.js文件是客户端的处理逻辑文件,包括发送和显示消息,连接服务器等

'use strict'// 获取页面组建
const userNameInput = document.querySelector('input#userName');
const roomInput = document.querySelector('input#room');const connectBtn = document.querySelector('button#connect');
const leaveBtn = document.querySelector('button#leave');const contentArea = document.querySelector('textarea#content');
const inputArea = document.querySelector('textarea#input');const sendBtn = document.querySelector('button#send');var socket;
// 连接逻辑
connectBtn.onclick = () => {//连接socket = io();// 成功加入后的逻辑socket.on('joined', (room, id) => {console.log(`join in successful,room=${room},socketId=${id}`);connectBtn.disabled = true;leaveBtn.disabled = false;inputArea.disabled = false;sendBtn.disabled = false;roomInput.disabled = true;userNameInput.disabled = true;});//离开成功的逻辑socket.on('leaved', (room, id) => {console.log(`user leave ,room=${room},socketId=${id}`);connectBtn.disabled = false;leaveBtn.disabled = true;inputArea.disabled = true;sendBtn.disabled = true;roomInput.disabled = false;userNameInput.disabled = false;socket.disconnect();});// 断开连接socket.on('disconnect', (socket) => {connectBtn.disabled = false;leaveBtn.disabled = true;inputArea.disabled = true;sendBtn.disabled = true;roomInput.disabled = false;userNameInput.disabled = false;});// 接受到消息的逻辑socket.on('message', (data) => {//窗口总是显示最后的内容contentArea.scrollTop = contentArea.scrollHeight;contentArea.value = contentArea.value + data + '\r';});// 发送加入的信令socket.emit('join', roomInput.value, userNameInput.value);
}//断开连接
leaveBtn.onclick = () => {socket.emit('leave', roomInput.value, userNameInput.value);
}//发送消息的逻辑
sendBtn.onclick = () => {sendMessage();
}// 回车发送消息的逻辑
inputArea.onkeypress = (event) => {//回车发送消息if (event.keyCode !== 13) {return;}sendMessage();//阻止默认行为event.preventDefault();
}function sendMessage() {let data = userNameInput.value + ' : ' + inputArea.value;socket.emit('message', roomInput.value, data);inputArea.value = '';
}

6、启动服务器

找到项目所在的目录,安装项目需要的模块

npm install express serve-index log4js socket.io

用以下命令启动服务器

node server.js

7、功能演示

打开两个浏览器的窗口,分别输入项目地址http://localhost/index.html(如果是别的ip,将localhost换成对应的ip地址),在浏览器上面输入用户名(不同),房间room(相同),点击connect按钮就可以发送消息。
在这里插入图片描述
另一个客户端:
在这里插入图片描述


后记
  个人总结,欢迎转载、评论、批评指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/156509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cesium 加载geojson数据类型点线面

1.获取geojson数据&#xff0c;本地新建一个.ts文件放置数据导出&#xff0c;并引入 获取geojson数据&#xff1a; DataV.GeoAtlas地理小工具系列 import { scGeojson } from ./geojson; 2.加载面 const addPolygonEvt () > {viewer.dataSources.add(Cesium.GeoJsonDataSo…

【计算机网络学习之路】Windows下的socket编程

文章目录 前言Windows下的socket编程1.预备工作2. socket编程 结束语 前言 本系列文章是计算机网络学习的笔记&#xff0c;欢迎大佬们阅读&#xff0c;纠错&#xff0c;分享相关知识。希望可以与你共同进步。 本篇文章仅记录Windows下socket编程和Linux的不同&#xff0c;并没…

云ES容灾方案

一、ES集群可用性容灾 1.1 云ES集群可用性容灾(使用跨可用区实例) 云ES集群部署在三个可用区,单可用区故障,云ES集群依然可能对外提供服务;两个可用区故障,需要进行控制台切流(集群会自动切的选择主节点) 应用服务部署在二个可用区,单可用区故障,依然可对提供服务1.2 …

开源网安解决方案荣获四川数实融合创新实践优秀案例

​11月16日&#xff0c;2023天府数字经济峰会在成都圆满举行。本次峰会由四川省发展和改革委员会、中共四川省委网络安全和信息化委员会办公室、四川省经济和信息化厅等部门联合指导&#xff0c;聚焦数字经济与实体经济深度融合、数字赋能经济社会转型发展等话题展开交流研讨。…

vue2【相关介绍】

目录 1&#xff1a;什么是单页面应用程序 2&#xff1a;什么是vue-cli 3&#xff1a;安装使用 4&#xff1a;vue项目的目录结构&#xff1a;​编辑 5&#xff1a;了解src目录的构成&#xff1a; 6&#xff1a;vue项目的运行流程 7&#xff1a;el&#xff1a;容器名称&…

ChatGPT暂时停止开通plus,可能迎来封号高峰期

前言: 前两日,chat gpt的创始人 San Altman在网上发表了,由于注册的使用量超过了他们的承受能力,为了确保每个人的良好使用体验,chat gpt将暂时停止开通gpt plus。 情况: 前段时间好像出现了官网崩溃的情况,就连api key都受到了影响,所以现在就开始了暂时停止plus的注…

本机idea连接虚拟机中的Hbase

相关环境&#xff1a; 虚拟机&#xff1a;Centos7 hadoop版本:3.1.3 hbase版本:2.4.11 zookeeper版本:3.5.7 Java IDE:IDEA JDK&#xff1a;8 步骤 步骤一&#xff1a;在idea创建一个maven项目 步骤二&#xff1a;在虚拟机里找到core-site.x…

如何在3dMax中使用Python返回场景内所有对象的列表?

如何在3dMax中使用Python返回场景内所有对象的列表&#xff1f; 3dMax支持开发基于Python的工具和扩展&#xff0c;因此可以对其进行自定义并将其集成到现代数字内容创建管道中。为此&#xff0c;3dMax集成了Python 3.9解释器&#xff0c;并通过pymxs API公开了3dMax的丰富功能…

如何有效的禁止Google Chrome自动更新?

禁止Chrome自动更新 1、背景2、操作步骤 1、背景 众所周知&#xff0c;当我们在使用Selenium进行Web自动化操作&#xff08;如爬虫&#xff09;时&#xff0c;一般会用到ChromeDriver。然而Driver的更新速度明显跟不上Chrome的自动更新。导致我们在使用Selenium进行一些操作时就…

工业交换机的六种分类

工业交换机可以按照不同的标准进行分类&#xff0c;具体有六种分类方法。我们今天就来简单了解一下这六种分类方法&#xff0c;它们分别是&#xff1a;工业交换机的管理标准、工业交换机的结构标准、工业交换机的网络位置、工业交换机的传输速率、工业交换机的工作协议以及工业…

提升--09-1--AQS底层逻辑实现

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、怎么解释AQS是什么&#xff1f;AQS的本质是JUC包下一个抽象类&#xff0c;AbstractQueuedSynchronizer &#xff08;抽象的队列式同步器&#xff09; 二、AQS核…

四川芸鹰蓬飞:抖店运营的时候注意什么?

抖店作为一个短视频平台&#xff0c;吸引了越来越多的商家加入。在抖店上进行有效的运营是提高销量和曝光度的关键。那么&#xff0c;抖店怎么设置运营呢&#xff1f;有哪些方法可以帮助商家在这个竞争激烈的平台上脱颖而出呢&#xff1f; 一、抖店怎么设置运营&#xff1f; 首…

微服务实战系列之加密RSA

前言 在这个时代&#xff0c;我们选择的人生目标已丰富多彩&#xff0c;秉持的人生态度也千差万别&#xff1a; 除了吃喝玩乐&#xff0c;还有科技探索&#xff1b; 除了CityWalk&#xff0c;还有“BookWalk”&#xff1b; 除了走遍中国&#xff0c;还有走遍世界&#xff1b; …

Selenium自动化测试详解

最近也有很多人私下问我&#xff0c;selenium学习难吗&#xff0c;基础入门的学习内容很多是3以前的版本资料&#xff0c;对于有基础的人来说&#xff0c;3到4的差别虽然有&#xff0c;但是不足以影响自己&#xff0c;但是对于没有学过的人来说&#xff0c;通过资料再到自己写的…

Spring-IOC-Spring6和JUnit5集成

1、父工程pom.xml <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>…

【FLink】水位线(Watermark)

目录 1、关于时间语义 1.1事件时间 1.2处理时间​编辑 2、什么是水位线 2.1 顺序流和乱序流 2.2乱序数据的处理 2.3 水位线的特性 3 、水位线的生成 3.1 生成水位线的总体原则 3.2 水位线生成策略 3.3 Flink内置水位线 3.3.1 有序流中内置水位线设置 3.4.2 断点式…

【shell】条件语句

一、测试 1.1文件测试test test命令是内部命令 test的语法 test 条件表达式 [ 条件表达式 ] test 选项 文件 -d &#xff1a;判断是否是目录 -f &#xff1a;判断是否是普通文件 -b &#xff1a;判断是否是块设备 -c &#xff1a;判断是否是字符设备 -e &#xff1a;判断是否…

【Python】给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。

问题描述 给出一个包含n个整数的数列&#xff0c;问整数a在数列中的第一次出现是第几个。 输入格式 第一行包含一个整数n。 第二行包含n个非负整数&#xff0c;为给定的数列&#xff0c;数列中的每个数都不大于10000。 第三行包含一个整数a&#xff0c;为待查找的数。 输出格式…

rv1126-rv1109-openssh

这是一个工具&#xff0c;可以通过ssh远程登录来操作&#xff0c;非常逆天&#xff01; 于是rv1109代码自身自带有openssh 所以只需要打开config即可 diff --git a/buildroot/configs/rockchip_rv1126_rv1109_spi_nand_defconfig b/buildroot/configs/rockchip_rv1126_rv1109…

Android codec2 视频框架之输出端的内存管理

文章目录 前言setSurfacestart从哪个pool中申请buffer解码后框架的处理流程renderOutbuffer 输出显示 前言 输出buffer整体的管理流程主要可以分为三个部分&#xff1a; MediaCodc 和 应用之间的交互 包括设置Surface、解码输出回调到MediaCodec。将输出buffer render或者rele…