前言
使用socket.io构建的Websocket服务和使用原始Websocket服务的区别:
-
使用原始的Websocket在客户端上发起的请求,除了一个websocket的请求外都是必要的网页请求。(构建Websocket请求代码详见上一篇文章 Websocket(1)Node构建Websocket服务)
而socket.io除了以上的请求,还多出了一堆HTTP请求
这多出来的请求解释如下:(参考:https://socket.io/docs/v4/how-it-works/)
(1)第一次请求:握手,从服务器中获取一些信息,包括sessionId
(2)第二次请求:发送你加的额外信息(HTTP长轮询)
(3)第三次请求:接收服务器发来的信息(HTTP长轮询)
(4)第四次请求:升级成WebSocket服务(WebSocket)
(5)第五次请求:接收数据(HTTP长轮询,WebSocket连接成功后关闭)
1. 安装socket.io :npm install socket.io
2. 在目录添加一个server.js
作为服务器和再创建一个static文件夹
,里面有一个index.html
和js文件夹
JS文件夹里放
socket.io.js
。socket.io.js
可以直接在node_modules\socket.io\client-dist
目录里复制,也可以在https://cdn.socket.io/官网目录下下载或引用
我这里遇到一个问题,当我使用
socket.io.js
时请求一直处在Pending状态,如下图。但当我把socket.io.js
改名为socket.js
或者socket2.io.js
就都可以加载成功,所以后面的index.html中我会用socket2.io.js
代替socket.io.js
。具体原因还有待查证。
3. server.js代码如下
const fs = require('fs');
const path = require('path');
//创建HTTP服务
const server = require("http").createServer((req, res) => {
//根据后缀名动态读取文件
let pathName = req.url;
//忽略掉socket.io的自发请求
if(pathName.indexOf("socket.io") > -1) return;
//默认路径为index.html路径
if(pathName === "/"){
pathName = "/index.html"
}
//获取扩展名
let extName = path.extname(pathName);
//读取文件
console.log(pathName)
res.statusCode = 200;
fs.readFile("static" + pathName, (err, data) => {
if(err){
res.end("error");
return;
}
res.setHeader('Content-Type', getMime(extName));
res.end(data)
})
})
const io = require("socket.io")({
serverClient: false
})
//将server附加到socket.io的engine.io,并添加额外的参数
io.attach(server, {
pnigInterval: 5000,
pingTimeout: 5000,
cookie: false
})
//连接成功的回调
io.on("connection", socket => {
console.log("client connected!!");
//发送消息给客户端
socket.send("hello client");
//处理客户端的socket.send事件
socket.on("message", data => {
console.log("client: " + data);;
})
//处理客户端的socket.emit事件
socket.on("chat_1", (elem1, elem2) => {
console.log("client: " + elem1 + elem2)
})
})
server.listen(3000, () => {
console.log("localhost:3000")
})
//根据不同的后缀名返回Content-Type值
function getMime(extName) {
switch(extName){
case '.html':
return "text/html";
case ".js":
return "application/json"
}
}
3. index.html代码如下
<html>
<head>
<meta charset="utf-8">
<title>socket.io</title>
<script src="./js/socket2.io.js"></script>
</head>
<body>
<script>
var socket = io("http://localhost:3000", {
reconnectionDelayMax: 10000,
auth: {
token: "123"
}
});
//连接服务器成功后的回调
socket.on("connect", () => {
console.log("server connected !!");
//发送消息给服务器
socket.send("hello server");
//传递多个参数
socket.emit("chat_1", "emit " ,"send message")
})
//接收到服务器消息的回调
socket.on("message", data => {
console.log("client: " + data)
})
</script>
</body>
</html>