先来展示我简单实现的单聊功能:
这是我在浏览器打开的两个聊天页面,实现的单聊功能,由于只是一个实验,所以就没太注意样式。
官方对socket.io的介绍:
使用LAMP (PHP)等流行的web应用程序堆栈编写聊天应用程序通常非常困难。它涉及到轮询服务器以查看更改、跟踪时间戳,而且它比应该的速度要慢得多。套接字在传统上是大多数实时聊天系统架构的解决方案,它提供客户机和服务器之间的双向通信通道。这意味着服务器可以向客户端推送消息。每当您编写一个聊天消息时,其思想是服务器将获得它并将其推给所有其他连接的客户机。
个人理解:
socket.io类似于WebSocket,同是一种在单个TCP连接上进行全双工通信的协议,socket使得客户端和服务端的数据交换变得更加简单,允许服务器主动向客户端推送信息。最重要的是,socket在前后端只需完成一次握手,两者就可以创建持久性的连接,也就是长连接,比如我这是在网页版实现的聊天,那么只有我关闭该浏览器页面,该连接才会断开,所谓的全双工,就是允许数据进行双向传输。
实现聊天功能通常都是使用socket实现,但也可以使用http实现,但不推荐,http是短链接,即完成一次交互就会断开连接,当用户要想接收到对方的信息时,就需要在间隔时间短的条件下不断轮询,问服务器有没有人给我发信息,这是非常浪费服务器资源的,也增大了服务器压力。。
1.搭建NodeJS服务端
1.首先搭建的是服务端,在项目目录下初始化:
npm install
项目目录会生成node_modules和package-lock.json文件。
2.服务端使用的是express框架:
npm install express --save
3.使用的socket版本是v2.3.0版本,更新的版本需要跨域
:
npm install [email protected] --save
想要看官方文档的可点击这里:socket.io官方文档
下面看代码:
var app = require('express')()
var server = require('http').createServer(app)
var io = require('socket.io')(server)
server.listen(80)
//客户端发起连接时触发
io.on('connection', (socket) => {
//每当一个用户登录,就会生成一个socket对象,此时的socket是对应正连接的客户端对象
//当用户连接成功后,向该客户端用户发送它自己的id,id特别重要,用于区分每个用户身份,正是用id才清楚发送方与接收方
//为什么它只会发送给刚连接的用户呢?因为这个socket就是刚连接的用户生成的。
//注意:第一个参数是自己定义的,只要前后端都对应即可
socket.emit('setId',{
id:socket.id})
//allUser中保存了每个连接的用户的数据,即id和用户名,
//由于新用户不知道之前有哪些旧用户,所以需要将这些已经在使用的用户发射给新用户,这样新用户才可以跟老用户聊天
socket.emit('allUser',allUser);
//广播api:它会向所有用户发送这个事件。由于它放在“连接”函数里面,所以只要有用户建立连接,就会发送这个事件
//为什么要广播给所有用户呢?当有新用户加入,当然要告知之前的用户,让它们更新“用户列表”,这样新旧用户才能发起聊天
//参数newUser是该新用户的信息
//我这里使用的是一个对象,对象里面有两个属性,分别是用户id和用户名
io.sockets.emit('addUser', newUser)
//这是实现单聊的api,使用on监听客户端发来的sendMsgToUser事件
//该事件携带发送的内容,data中有发送者和接收者的id和聊天内容
//注意接收方的id是必须的,因为要通过接收方id,服务器才知道要把聊天内容发给谁
//这里我之所以也传发送方的id,是为了让它知道是谁给它发信息
socket.on('sendMsgToUser', (data) => {
/**
* data类型:
* data:{
* from:"发送者id",
* to:'接收者id',
* content:'发送的内容'
* }
*/
//根据id,向接收方发射simpleChat事件,携带发送方发过来的data,即服务器只是起到转发作用
socket.to(data.to).emit('simpleChat', data)
})
})
}
我相信看了上面的解释你们能理解服务器的socket的用法与作用。这些事件都是在用户发起连接时就绑定的监听事件。
2. 前端搭建
由于是一个小实验报告,为了减少代码体积,就没有使用框架,同时我们也不直接下载socket.io包,而是直接去github中复制socket.io的压缩代码:socket.io地址
图示:
在前端目录下新创一个socket.io.js文件,把复制的代码粘贴进去。
再创建一个index.html文件引入js文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>聊天室</title>
<link rel="stylesheet" href="./index.css" />
<script src="./socket.io.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<script>
//引入socket.io.js文件成功的话,就可以在全局引用io对象
//下面一句代码就是会连接上后端运行的服务器,并返回一个socket,只是我用conn表示而已
var conn = io.connect('http://localhost')
//监听,获取自身id
conn.on('setId', (data) => {
//在后端那里说过,当连接成功后,服务器会返回当前用户连接的id,在这里你可以保存好,在发送信息可以使用
})
conn.on('allUser',(data)=>{
//保存所用用户信息,将所有用户展示在用户列表上
})
//监听是否有新用户加入
conn.on('addUser', (data) => {
//将这个新用户信息展示在用户列表中
})
//监听用户发来的信息
conn.on('sendMsgToUser', (data) => {
//假如xxx给我发送消息,那么当我点击用户列表的xxx时,聊天内容模板就给我展示聊天内容即可
//要想做到有聊天记录,由于没有使用数据库,那你也可以在前端将与每个用户的聊天内容分别保存起来
//当我点击哪个用户,就给我展示我与ta的聊天记录即可
})
//发送信息
//将发送按钮的点击事件绑定给这个函数,当点击按钮时,就将信息发送
function sendMsg(){
let msg={
from:'由于是我给别人发送消息,那么就是我的id,我的id在上面已经保存了',
to:'接收方的id',
content:''获取输入框输入的内容
};
conn.emit('sendMsgToUser', msg)
}
</script>
</body>
</html>
这篇博客主要讲解socket实现单聊的关键api和思想,知道了如何实现单聊的思想和socket的api使用,剩下的就是如何设计聊天框,在这里就不再讲述。