nodejs死亡笔记之socket.io那些事(附可用来撩妹的聊天功能)

2023-11-07 04:30

本文主要是介绍nodejs死亡笔记之socket.io那些事(附可用来撩妹的聊天功能),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我相信有很多人是看到撩妹才进来的,别急,我们要一步一步来。

websocket简介

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。

现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客服端的浏览器,这种方式有一个很大的弊端,就是会占用很多的带宽。

最新的轮询效果是Comet – 用了AJAX。但这种技术虽然可达到全双工通信,但依然需要发出请求。

使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送。而且它为我们实现即时服务带来了两大好处:

节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。
推送信息:不需要客户端请求,服务器可以主动传送数据给客户端。

实现了websocket的浏览器:

TablesAre
chromeSupported in version 4+
FirefoxSupported in version 4+
Internet ExplorerSupported in version 10+
OperaSupported in version 10+
SafariSupported in version 5+

有些迫不及待想撩妹的 很生气,不是讲socket.io么,你扯websocket干嘛。我只能给你个关爱智障的眼神-.-

socket.io

Socket.IO是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。

socket.io的特点

  • 易用性:socket.io封装了服务端和客户端,使用起来非常简单方便。
  • 跨平台:socket.io支持跨平台,这就意味着你有了更多的选择,可以在自己喜欢的平台下开发实时应用。
  • 自适应:它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5。

体验socket.io

首先,创建一个项目,安装socket.io模块

npm install socket.io

接下来,新建一个test.js文件:

var io = require('socket.io');var io = require('socket.io')(80);//监听80端口

为什么要监听80端口呢?因为我懒得写3000。。。80是默认端口,可以不输入的。

接下来,注册一个事件:

io.on('connection',function(socket){//连接成功...socket.on('disconnect',function(){//用户已经离开...});
});

connection事件在客户端成功连接到服务端时触发,有了这个事件,我们可以随时掌握用户连接到服务端的信息。

当客户端成功建立连接时,在connection事件的回调函数中,我们还是可以为socket注册一些常用的事件,如:disconnect事件,它在客户端连接断开是触发,这时候我就知道用户已经离开了。


目前为止,我们已经搭建好了一个最简单的socket服务器,为了在浏览器中能够访问到我们的服务,我们还需要在服务端搭建一个简单的web服务器,让浏览器能够访问我们的客户端页面。

为了便捷,我们选用node.js中常用的express框架来实现web服务,示例如下:

var express = require('express');
var app = express();
app.get('/',function(req,res){res.status(200).send('欢迎学习nodejs!');
});
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection',function(socket){});
server.listen(80);

服务端构建完毕,下面看一看客户端应该如何使用。

服务端运行后会在根目录动态生成socket.io的客户端js文件,客户端可以通过固定路径/socket.io/socket.io.js添加引用。

首先添加网页index.html,并在网页中引用客户端js文件

<script src="/socket.io/socket.io.js"></script>

当然这样的客户端引用方式并不是必须的,我们也可以引用官方的cdn或者下载到本地的客户端文件。一般情况下推荐引用动态生成的客户端文件,因为这样客户端和服务端的版本可以保持一致,减少出错的几率。

//官方CDN
<script src="https://cdn.socket.io/socket.io-1.2.1.js"></script>

当客户端成功加载socket.io客户端文件后会获取到一个全局对象io,我们将通过io.connect函数来向服务端发起连接请求。

var socket = io.connect('/');
socket.on('connect',function(){//连接成功
});
socket.on('disconnect',function(data){//连接断开
});

connect函数可以接受一个url参数,url可以socket服务的http完整地址,也可以是相对路径,如果省略则表示默认连接当前路径。与服务端类似,客户端也需要注册相应的事件来捕获信息,不同的是客户端连接成功的事件是connect。

了解了客户端如何使用,下面我们创建网页index.html,并添加如下内容(保存):

<html>
<head><script src="/socket.io/socket.io.js"></script><script>window.onload = function(){var socket = io.connect('/');socket.on('connect',function(){document.write('连接成功!');});};</script>
</head>
<body>
</body>
</html>

页面添加完毕还要记得在服务端app.js中为它添加路由,让我们可以访问测试网页:

app.get('/index',function(req,res){res.sendFile('index.html',{root:__dirname});
});

最后一步:通信

示例-客户端向服务端发送消息(index.html):

var socket = io.connect('/');
socket.on('connect',function(){//客户端连接成功后发送消息'hello world!'socket.send('hello world!');
});
socket.on('message',function(data){alert(data);
});

连接成功后,我们向服务端发送消息hello world!,还为socket注册了message事件,它是send函数对应的接收消息的事件,当服务端向客户端send消息时,我们就可以在message事件中接收到发送过来的消息。

服务端向客户端发送消息也可以通过send的方式,示例 - 服务端向客户端发送消息(app.js):

var io = require('scoket.io');
io.on('connection',function(socket){socket.send('welcome!');socket.on('message',function(data){//收到消息console.log(data);});
});

到现在为止,socket.io的基本用法就结束了,看起来蛮简单的,接下来,稍微提一下socket.io的其他用法及原理。

socket.io是如何发送消息的?
在socket.io中,emit函数用于发送数据,还记得在入门篇中,我们使用send的方式实现了信息的互发,其实send函数只是emit的封装,实际上还是使用了emit,且看send函数是如何实现的:

function send(){var args = toArray(arguments);args.unshift('message');this.emit.apply(this, args);return this;
}

在send函数中,获取到原来的参数,并在原来的基础上插入了一个参数message,然后调用了emit函数。通过send函数的实现,我们也学会了emit函数的用法,它有连个参数,第一个参数是事件名称,在接收端注册该事件就可以接收到发送过去的信息,事件名称可以自由定义,在不同的场景下,我们可以定义不同的事件来接收消息。第二个参数才是发送的数据。了解清楚了工作原理,下面来将send替换成emit函数发送信息:

//app.js
io.on('connection',function(socket){socket.emit('message','连接成功!');socket.on('message',function(data){});
});

socket.io的命名空间

命名空间着实是一个非常实用好用的功能。我们可以通过命名空间,划分出不同的房间,在房间里的广播和通信都不会影响到房间以外的客户端。

那么如何创建房间呢?在服务端,通过of(“”)的方式来划分新的命名空间:

io.of('chat').on('connection',function(socket){});

示例中,我们创建一个名为chat的房间,客户端可以通过如下方式连接到指定的房间:

var socket = io.connect('/chat');

虽然连接到指定的房间,但是我们也可以在服务端操作,自由的进出房间:

socket.join('chat');//进入chat房间
socket.leave('chat');//离开chat房间

socket.io的广播消息

在实时应用中,广播是一个不可或缺的功能,socket.io提供两种服务端广播方式。

第一种广播方式可以称之为’全局广播’,顾名思义,全局广播就是所有连接到服务器的客户端都会受到广播的信息:

socket.broadcast.emit('DATA',data);

但是,在实际应用场景中,我们很多时候并不需要所有用户都收到广播信息,有的广播信息只发送给一部分客户端,比如某个房间里面的用户,那么可以使用如下方式:

socket.broadcast.to('chat').emit('DATA',data);

当使用to()的方式广播信息时,只有该命名空间下的客户端才会收到广播信息,是不是很方便呢。

sockei.io的中间件

socket.io提供中间件功能,我们可以通过中间件来对请求进行预处理,比如身份验证:

io.use(function(socket, next){if (socket.request.headers.cookie) return next();next(new Error('Authentication error'));
});

示例中展示了通过中间件进行身份验证,当没有cookie的时候抛出异常。

socket.io传递参数的方法

在很多应用场景中,客户端发起连接请求时都需要传递参数,这些参数可能是身份验证、初始化设置等等,那么socket.io发起连接时如何传递参数呢?

var socket = io.connect('/');

由于connect函数发起连接的参数是一个url,你可能会想到把参数拼接到url上,如http://xxxx?xx=xxxx,但是很遗憾这样是行不通的,我们可以通过这样的方式来传递参数:

var socket = io.connect('/',{ _query:'sid=123456' });

在服务端可以这样获取到传递的参数:

io.use(function(socket){var query = socket.request._query;var sid = query.sid; 
});

客户端传递的参数已经被解析成了一个json对象,这个对象就是_query。

好了,socket.io的讲解就到这里,接下来是大家最喜欢的撩妹环节。

撩妹技巧之聊天的实现

1。创建一个express项目(方法还是那个方法)
2。假如socket.io模块
3。修改routes目录下的index.js:

var express = require('express');
var router = express.Router();
var socket_io = require('socket.io');router.get('/', function(req, res, next) {res.send('response');
});router.prepareSocketIO = function (server) {var io = socket_io.listen(server);io.sockets.on('connection',function (socket) {socket.on('join',function (user) {socket.user = user;socket.emit('state','server',true);socket.broadcast.emit('state','server',user+"online");});socket.on('sendMsg',function (msg) {socket.emit('chat',socket.user,msg);socket.broadcast.emit('chat',socket.user,msg);});});
}module.exports = router;

4。在app.js中添加代码:

app.ready=function(server){routes.prepareSocketIO(server);
}

5。在www文件里添加代码

app.ready(server);

6。在public目录下创建chat.html:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title></title><script src="http://code.jquery.com/jquery-2.1.1.min.js"></script><script src="/socket.io/socket.io.js"></script><link href="/stylesheets/style.css" type="text/css" rel="stylesheet">
</head>
<body>
<div><table id="content"></table>
</div><table class="tool"><tr><td class="left"><div id="textContent" contenteditable="true" type="text"></div></td><td><button id="send">发送</button></td></tr>
</table>
<script>var socket = io.connect('http://127.0.0.1:3000');var userName = "访客某某";socket.on('connect', function () {userName = prompt("请输入你的姓名?") || userName;socket.emit('join', userName);});socket.on('chat', function (user, data) {if (user === userName) {$('<tr class="align-right"><td><span><span class="msg">' + data + '</span>' + user + '</span></td></tr>').appendTo($('#content'));} else {$('<tr class="align-left"><td><span >' + user + '<span class="msg">' + data + '</span></span></td></tr>').appendTo($('#content'));}p.className = direct;});$('#send').click(function () {var content = $('#textContent').html();if (content = content.replace(" ", "")) {socket.emit('sendMsg', content);$('#textContent').html("");}});
</script>
</body>
</html>

7。在public/stylesheets目录下的style.css中添加:

table {width: 100%;
}table.tool {position: fixed;bottom: 0;left: 0;right: 0;padding: 10px;
}#content {height: auto;padding: 10px;padding-bottom: 32px;
}#content tr {margin-bottom: 10px;
}
#textContent {border: 1px solid grey;border-radius: 5px;padding: 6px;
}.left {width: 88%;
}#send {width: auto;padding: 2px 12px;line-height: 26px !important;border-radius: 5px;font-weight: bold;color: white;background-color: #ff4400;
}tr.align-left td > span {float: left;
}tr.align-left td > span span {display: inline-block;
}tr.align-right td > span {float: right;
}tr.align-right td > span span {display: inline-block;
}span .msg {padding: 6px;background-color: #00B7FF;border: 1px solid #00B7ee;border-radius: 5px;
}.timer {display: block;text-align: center;
}

目录结构:
这里写图片描述

之后就可以愉快的聊天了。启动服务,在浏览器中输入http://localhost:3000/chat.html,同时打开两个页面就可以聊天了。

如图:
这里写图片描述

项目代码放在github上:https://github.com/CleverFan/nodejsStudy/tree/master/expressTest/day03_socketio

ps 具体怎么撩妹我还没想好,你们自己想吧,哈哈哈哈哈

这篇关于nodejs死亡笔记之socket.io那些事(附可用来撩妹的聊天功能)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/361259

相关文章

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

安装nodejs环境

本文介绍了如何通过nvm(NodeVersionManager)安装和管理Node.js及npm的不同版本,包括下载安装脚本、检查版本并安装特定版本的方法。 1、安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 2、查看nvm版本 nvm --version 3、安装

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个