我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

上一篇文章里面,讲解socket.io的最基本最简单的使用方式。在文章的末尾,苏南大叔提出了关于实际的代码里面,有关文件路径的一些问题。首先,客户端初始化的时候,io()里并没有传递任何协议路径之类的信息。其次,在资源请求的时候,路径中存在着/socket.io/的固定字符串。如何自定义这个固定字符串呢?

苏南大叔:Socket.io双向通信教程,如何更改路径相关设置? - socket
Socket.io双向通信教程,如何更改路径相关设置?(图6-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10nodejs@20.18.0express@4.21.2socket.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
Socket.io双向通信教程,如何更改路径相关设置?(图6-2)

如果把socket.io的客户端代码/socket.io/socket.io.js,部署到别的服务器的话,就不在本文讨论范围内了。

socket.io伺服源码

查看socket.io服务端的源码,文件node_modules\socket.io\dist\index.jsline246,所有的疑问得到解决。

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);
        // ...
    });
}

苏南大叔:Socket.io双向通信教程,如何更改路径相关设置? - 只处理目标文件请求
Socket.io双向通信教程,如何更改路径相关设置?(图6-3)

这段代码,还演示了etag的使用方法,值得借鉴。

参数serveClient

根据上述源码的阅读,可以增加参数serveClient:falsesocket.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/目录。
  • 或者使用其它网络地址,可能会面临跨域问题【不推荐】。

苏南大叔:Socket.io双向通信教程,如何更改路径相关设置? - 交给express处理
Socket.io双向通信教程,如何更改路径相关设置?(图6-4)

参数 path

有关url中的/socket.io/字符串的控制。举例如下:

如果要修改其中的/socket.io/字样,解决方案就是:
在初始化的时候,传入path参数。两边都有这个参数,需要:

  • 保证服务器和客户端参数设置一致。
  • 保证新的路径参数不能和额外处理的socket.io.js文件路径冲突。

苏南大叔:Socket.io双向通信教程,如何更改路径相关设置? - path参数
Socket.io双向通信教程,如何更改路径相关设置?(图6-5)

服务器参数 path

//...
const socketio = require("socket.io");
const io = socketio(expressServer,{
    //serveClient: false,
    path:"/.io",
});
//...

客户端参数 path

<script>
const socket = io({ path:'/.io' });
// ..
</script>

苏南大叔:Socket.io双向通信教程,如何更改路径相关设置? - 设置路径
Socket.io双向通信教程,如何更改路径相关设置?(图6-6)

服务接口路径

值得一提的是:默认情况下,客户端代码代码里面,并不像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自身的原始设定有关系。敬请关注苏南大叔的系列文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   socket