Socket.io双向通信教程,如何更改路径相关设置?
发布于 作者:苏南大叔 来源:程序如此灵动~
上一篇文章里面,讲解socket.io
的最基本最简单的使用方式。在文章的末尾,苏南大叔提出了关于实际的代码里面,有关文件路径的一些问题。首先,客户端初始化的时候,io()
里并没有传递任何协议路径之类的信息。其次,在资源请求的时候,路径中存在着/socket.io/
的固定字符串。如何自定义这个固定字符串呢?
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10
,nodejs@20.18.0
,express@4.21.2
,socket.io@4.8.1
。本文讲解socket.io
路径相关问题。
聚焦代码
socket.io
的基础使用例子:
服务器端代码:
//...
const socketio = require("socket.io");
const io = socketio(expressServer);
//...
客户端代码:
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
//...
</script>
客户端 socket.io.js 路径
客户端引入socket.io.js
的方式是:
<script src="/socket.io/socket.io.js"></script>
服务器上并不存在/socket.io/socket.io.js
这个文件。目前,服务器上是express
+socket.io
的组合,如果express
没有对这个请求进行处理的话,它就是由socket.io
的服务端来处理的。
如果把socket.io
的客户端代码/socket.io/socket.io.js
,部署到别的服务器的话,就不在本文讨论范围内了。
socket.io伺服源码
查看socket.io
服务端的源码,文件node_modules\socket.io\dist\index.js
,line246
,所有的疑问得到解决。
if (this._serveClient) {
app.get(`${this._path}/*`, (res, req) => {
if (!this.clientPathRegex.test(req.getUrl())) {
req.setYield(true);
return;
}
const filename = req
.getUrl()
.replace(this._path, "")
.replace(/\?.*$/, "")
.replace(/^\//, "");
const isMap = dotMapRegex.test(filename);
// ...
});
}
这段代码,还演示了etag
的使用方法,值得借鉴。
参数serveClient
根据上述源码的阅读,可以增加参数serveClient:false
,socket.io
的服务端就放弃对socket.io.js
的处理了。例如:
//...
const socketio = require("socket.io");
const io = socketio(expressServer,{
serveClient: false,
});
//...
但是它依然对url
中的path
参数进行控制,也就是/socket.io/socket.io.js
中的/socket.io
字样。所以目前的处理方案是:
- 自己独立处理的
socket.io.js
文件,暂时放弃目录名/socket.io/
,改成了/socket/
目录。 - 或者使用其它网络地址,可能会面临跨域问题【不推荐】。
参数 path
有关url
中的/socket.io/
字符串的控制。举例如下:
- http://localhost/socket.io/socket.io.js
- http://localhost/socket.io/?EIO=4&transport=polling&t=5jc4vxgg
- ws://localhost/socket.io/?EIO=4&transport=websocket&sid=Sk-vzzSLCvUqqs2MAAAE
如果要修改其中的/socket.io/
字样,解决方案就是:
在初始化的时候,传入path
参数。两边都有这个参数,需要:
- 保证服务器和客户端参数设置一致。
- 保证新的路径参数不能和额外处理的
socket.io.js
文件路径冲突。
服务器参数 path
//...
const socketio = require("socket.io");
const io = socketio(expressServer,{
//serveClient: false,
path:"/.io",
});
//...
客户端参数 path
<script>
const socket = io({ path:'/.io' });
// ..
</script>
服务接口路径
值得一提的是:默认情况下,客户端代码代码里面,并不像websocket
一样,指定了服务接口地址,例如:ws://localhost/
。它的服务接口地址,就取当前html
的所在的域名。
那么,如果有修改服务接口地址的需求的话,可以参考下面的解决方案。
客户端
<script>
const socket = io("https://localhost:82");
// ..
</script>
但是,更换这个非当前域名的接口地址的话,又存在【一定的】概率,引发跨域问题,这事儿待后续更新。
代码综述
本文所描述的路径相关的代码,整理组合如下:
服务端:
//...
const socketio = require("socket.io");
const io = socketio(expressServer,{
serveClient: false, // 是否空值客户端文件
path:"/.io/", // 客户端所有请求路径,注意和客户端设定保持一致
});
//...
客户端:
<script src="/socket/socket.io.js"></script>
<script>
const socket = io(
"https://localhost:82", // 一定概率下,会出现跨域问题
{ path:'/.io/' } // 注意和服务端的path设定保持一致
);
// ...
</script>
结语
本文中留下的伏笔就是:接口路径的跨域问题。为什么是【有一定概率】呢?这还和socket.io
自身的原始设定有关系。敬请关注苏南大叔的系列文章:


