いつもは すでにリッスン中なら
Error: listen EADDRINUSE: address already in use 0.0.0.0:3000
みたいなエラーになります
なのにそうならずにリッスンできるケースがありました
アクセスしてみると あとからリッスンした方に接続されました
そのプロセスを止めると先にリッスンしていた方に接続されました
これは結構便利そうと思ってどうなってるのか調べていると リッスンするときのホスト名が関係してるようでした
これができる条件を探してみると 片方が Node.js の生の http モジュールを使って もう片方がライブラリを使う場合の組み合わせでした
ライブラリの内部を見ると ホスト名に localhost を指定してました
普通に http.createServer().listen() をホスト名を省略して使うと 0.0.0.0 になります
ここが違うとエラーにならず両方リッスンできるようです
つまり この listen1.js と listen2.js を同時に実行すると両方とも成功します
[listen1.js]
require("http").createServer((req, res) => {
res.end("OK1")
}).listen({ port: 3000, host: "0.0.0.0" }, () => console.log("listen1"))
.on("error", console.error)
[listen2.js]
require("http").createServer((req, res) => {
res.end("OK2")
}).listen({ port: 3000, host: "localhost" }, () => console.log("listen2"))
.on("error", console.error)
後勝ちなのかなと思ったのですが順番ではなく localhost が優先されてるようでした
また 127.0.0.1 でアクセスすると 0.0.0.0 の方に届くようです
C:\>curl http://localhost:3000
OK2
C:\>curl http://127.0.0.1:3000
OK1
ホスト名を変えればいくつでもできるのかなと思って試したのですが 存在しないホスト名だとエラーでした
ですが hosts に追加して foo を 127.0.0.1 にすれば foo でもリッスンできました
それならこの方法でバーチャルホストみたいなことができるの?と思ったのですが bar も追加してリッスンするとここはエラーでした
0.0.0.0 と localhost とその他の 3 つまでみたいです
foo と bar を両方 127.0.0.1 にすると両方リッスンできないなら localhost も同じになりそうですが Windows の場合 localhost は WSL 関係の都合で特殊扱いされてるのもかもしれません
Linux だとどうなるのかとやってみると 0.0.0.0 と localhost の 2 つを同時にリッスンすることはできませんでした
Windows が特殊なのかもしれません