Heroku部署Node.js网页游戏服务器端口监听问题求助
解决Heroku部署时端口监听冲突的问题
你遇到的核心问题是代码同时在index.js和network.js中创建了独立的HTTP服务器并监听端口,而Heroku平台只允许单个进程监听它分配的动态端口(通过process.env.PORT获取),重复监听会直接导致应用崩溃。下面是针对性的修改方案:
1. 调整index.js:统一管理HTTP服务器与socket.io
我们需要在index.js中显式创建HTTP服务器,绑定socket.io后再传递给network模块,避免重复创建服务。修改后的代码如下:
var express = require('express'); var app = express(); // 优先使用Heroku分配的端口,本地开发 fallback 到5000 var port = process.env.PORT || 5000; // 显式创建HTTP服务器(替代app.listen的简写形式) var http = require('http').Server(app); // 将socket.io绑定到这个HTTP服务器上 var io = require("socket.io")(http); app.use(express.static(__dirname + '/')); // 全局配置常量 var WORLD_SX = 128; var WORLD_SY = 128; var WORLD_SZ = 32; var WORLD_GROUNDHEIGHT = 16; var SECONDS_BETWEEN_SAVES = 60; var ADMIN_IP = "127.0.0.1"; // 加载模块 var modules = {}; modules.helpers = require("./js/helpers.js"); modules.blocks = require("./js/blocks.js"); modules.world = require("./js/world.js"); modules.network = require("./js/network.js"); modules.fs = require("fs"); var log = require("util").log; // 设置全局变量 global.Vector = modules.helpers.Vector; global.BLOCK = modules.blocks.BLOCK; // 初始化游戏世界 var world = new modules.world.World(WORLD_SX, WORLD_SY, WORLD_SZ); // 传入已绑定好的socket.io实例初始化游戏服务器(第二个参数是最大玩家数,可按需修改) var gameServer = new modules.network.Server(io, 10); // 统一在index.js中启动端口监听 http.listen(port, function() { console.log('Node app is running on port', port); });
2. 修改network.js的Server函数:移除独立服务创建逻辑
让Server函数不再自行创建HTTP服务器,直接使用传入的socket.io实例即可。修改后的代码片段:
function Server(socketio, slots) { var io = this.io = socketio; // 复用传入的socket.io实例 var s = this; io.sockets.on("connection", function(socket) { s.onConnection(socket); }); this.eventHandlers = {}; this.activeNicknames = {}; this.activeAddresses = {}; this.maxSlots = slots; this.usedSlots = 0; this.oneUserPerIp = true; // 移除原有的http.listen调用,端口监听已统一放在index.js中完成 }
方案说明
- Heroku的端口是动态分配的,必须通过
process.env.PORT获取,不能硬编码5000(本地开发可保留fallback)。 - 把HTTP服务的创建和端口监听统一放在
index.js中,让network模块复用已有的socket.io实例,彻底避免端口冲突。 - 这样修改后,本地开发和Heroku部署都能正常运行,无需额外适配。
内容的提问来源于stack exchange,提问作者Fico Pangestu




