节点服务器进程在 Ubuntu 服务器上工作,但不是家庭 Ubuntu PC 本地主机



我正在开发一个小型MMO,它目前正在我设置的远程Ubuntu服务器上提供服务。在我修复了本地节点版本的问题后,服务器进程现在在我的家用计算机上运行良好,但 localhost 中没有任何内容(除了最初的 Apache 默认页面,但我关闭了 Apache 进程以阻止它阻止端口 80)。我正在使用node server.js运行代码(好吧,forever server.js在服务器中,但出于这些目的,它是相同的)。代码如下:

服务器.js

String.prototype.endsWith = function (suffix)
{
return (this.indexOf(suffix, this.length - suffix.length) !== -1);
}
String.prototype.startsWith = function (prefix)
{
return (this.substr(0, prefix.length) == prefix);
}
String.prototype.contains = function (toSearch)
{
return (this.indexOf(toSearch) != -1);
}
Array.prototype.inArray = function (obj)
{
for (var i = 0; i < this.length; i++)
if (this[i] == obj)
return true;
return false;
}
Array.prototype.append = function (arr)
{
for (var i = 0; i < arr.length; i++)
this[this.length] = arr[i];
}
String.prototype.leftPad = function (char, length)
{
var result = this;
while (result.length < length)
{
result = char + result;
}
return result;
}
String.prototype.hashPassword = function (salt)
{
var crypto = require('crypto');
return crypto.createHash('sha256').update(salt + this).digest('base64');
}
var nextPlayerId = 1;
var app = require('http').createServer(handler),
url = require("url"),
io = require('socket.io').listen(app, { log: false }),
path = require("path"),
fs = require('fs');
var zlib = require('zlib');
var config = require('./config');
GLOBAL.secureKey = config.secureKey;
io.enable('browser client minification');
io.sockets.on('connection', socketHandler);
var knownExt = [
['.html', 'text/html'],
['.js', 'text/javascript'],
['.css', 'text/css'],
['.png', 'image/png'],
['.jpg', 'image/jpeg'],
['.gif', 'image/gif'],
['.mp3', 'audio/mpeg'],
['.ogg', 'audio/ogg'],
['.dae', 'text/plain']
];
var moduleDirs = ['modules/', 'admin/', 'object_codes/', 'block_codes/', '3dgeometry/'];
var worldGenModuleDirs = ['special_areas/', 'world_details/'];
GLOBAL.getDb = function ()
{
var mongodb = require("mongodb"),
mongoserver = new mongodb.Server("localhost", 27017, {});
return new mongodb.Db(config.dbName, mongoserver, {safe: true});
}
GLOBAL.after_login = new Array();
GLOBAL.after_disconnect = new Array();
GLOBAL.socketFunctions = new Array();
GLOBAL.socketFunctions[GLOBAL.socketFunctions.length] = {name: 'ping', action: function (socket, data)
{
socket.pingDate = new Date();
}};
GLOBAL.socketFunctions[GLOBAL.socketFunctions.length] = {name: 'position', action: socketPositionUpdate};
GLOBAL.socketFunctions[GLOBAL.socketFunctions.length] = {name: 'disconnect', action: function (socket, data)
{
var playerId = socket.playerId;
//socket.broadcast.emit('player_disconnect', {playerId: socket.playerId});
// Remove useless sockets
for (var i = 0; i < GLOBAL.sockets.length; i++)
{
if (playerId == GLOBAL.sockets[i].playerId)
{
GLOBAL.sockets.splice(i, 1);
break;
}
}
/*for (var i = 0; i < GLOBAL.sockets.length; i++)
GLOBAL.sockets[i].emit('player_disconnect', {playerId: playerId});*/
socket.broadcast.emit('player_disconnect', {playerId: playerId});
for (var i = 0; i < GLOBAL.after_disconnect.length; i++)
GLOBAL.after_disconnect[i](socket);
}};
setInterval(checkTimeout, 1000);
GLOBAL.updatePositionFunctions = new Array();
GLOBAL.specialUri = new Array();
GLOBAL.sockets = new Array();
require('./user_storage.js');
require('./map_storage.js');
require('./general_data.js');
require('./wiki.js');
require('./chat.js');
require('./chat_bot.js');
require('./chat_bot_sentences.js');
require('./player_market.js');
require('./player_owned_areas.js');
require('./news.js');
require('./books.js');
require('./payment_done.js');
var baseDir = process.cwd();
if (baseDir.endsWith('server'))
{
baseDir = path.resolve(baseDir, "..");
}
//console.log(baseDir);
function handler(request, response)
{
var uri = url.parse(request.url).pathname;
if (uri == "/")
uri = "/index.html"
else if (uri == "/chat" || uri == "/chat/")
uri = "/chat/index.html";
for (var i = 0; i < GLOBAL.specialUri.length; i++)
{
if (uri.substr(0, GLOBAL.specialUri[i].name.length) == GLOBAL.specialUri[i].name)
{
GLOBAL.specialUri[i].action(request, response);
return;
}
}
var filename = path.join(baseDir, uri);
if (uri == "/index.html")
{
mainFile(request, response);
return;
}
if (uri == "/welcome.html")
{
welcomeFile(request, response);
return;
}
else if (uri == "/allModulesCode.js")
{
modulesCode(request, response);
return;
}
/*else if (uri == "/cv.appcache")
{
manifestFile(request, response);
return;
}*/
fs.exists(filename, function (exists)
{
var isOk = true;
try
{
if (!exists)
isOk = false;
else if (fs.statSync(filename).isDirectory())
isOk = false;
}
catch (err)
{
isOk = false;
}
if (uri.startsWith("/server/"))
isOk = false;
if (uri.contains("..") || uri.contains("./") || uri.contains("/."))
isOk = false;
if (!isOk)
{
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Foundn");
response.end();
return;
}
for (var i = 0; i < knownExt.length; i++)
{
if (filename.endsWith(knownExt[i][0]))
{
try
{
if (filename.endsWith('.js') || filename.endsWith('.html'))
{
response.writeHead(200, {"Content-Type": knownExt[i][1], "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache"});
fs.createReadStream(filename).pipe(response);
}
else if (filename.endsWith('.css'))
{
response.writeHead(200, {"Content-Type": knownExt[i][1], "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache"});
cssCode(filename, response);
}
else
{
response.writeHead(200, {"Content-Type": knownExt[i][1], "Cache-Control": "max-age=31536000", "Cache-Control": "public", "Expires": new Date(((new Date()).getTime() + 1000 * 31536000))});
fs.createReadStream(filename).pipe(response);
}
}
catch
(ex)
{
console.log(ex)
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Foundn");
response.end();
}
return;
}
}
response.writeHead(404, {"Content-Type": "text/plain"});
response.write("404 Not Foundn");
response.end();
}
);
}
function modulesCode(request, response)
{
response.writeHead(200, { "Content-Type": "text/javascript", "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache" });
response.write("var codeLines=[];");
var nbLines = 1;
var allDirs = [];
for (var j = 0; j < moduleDirs.length; j++)
allDirs[allDirs.length] = moduleDirs[j];
for (var j = 0; j < worldGenModuleDirs.length; j++)
allDirs[allDirs.length] = worldGenModuleDirs[j];
for (var j = 0; j < allDirs.length; j++)
{
var files = fs.readdirSync(baseDir + '/' + allDirs[j]);
for (var i = 0; i < files.length; i++)
{
if (files[i].endsWith(".js"))
{
response.write("n// ----------------------------n");
response.write("// " + allDirs[j] + "/" + files[i] + "n");
nbLines += 4;
var data = fs.readFileSync(baseDir + '/' + allDirs[j] + "/" + files[i], "utf8");
var dataLines = data.split('n').length;
response.write("codeLines[codeLines.length]={fromLine:" + nbLines + ",toLine:" + (nbLines + dataLines) + ",name:'" + allDirs[j] + "/" + files[i] + "'}n");
nbLines += dataLines;
response.write("// ----------------------------n");
response.write(data);
}
}
}
response.write("nn// ----------------------------n");
response.write("// images datesn");
response.write("// ----------------------------n");
response.write("var imageVersion={};n");
var contentDirs = ['/images', '/3dmodels'];
for (var j = 0; j < contentDirs.length; j++)
{
var files = fs.readdirSync(baseDir + contentDirs[j]);
for (var i = 0; i < files.length; i++)
{
var s = fs.statSync(baseDir + contentDirs[j] + '/' + files[i]);
response.write("imageVersion['" + files[i] + "']='" + s.mtime.getTime() + "';n");
}
}
response.write("n// ----------------------------n");
response.write("// Initn");
response.write("initialize();");
/*var code = "";
code += "var codeLines=[];";
var nbLines = 1;
var allDirs = [];
for (var j = 0; j < moduleDirs.length; j++)
allDirs[allDirs.length] = moduleDirs[j];
for (var j = 0; j < worldGenModuleDirs.length; j++)
allDirs[allDirs.length] = worldGenModuleDirs[j];
//var path = require('path');
var mustUpdated = true;
if (fs.existsSync(baseDir + '/cache/allModulesCode.js'))
{
mustUpdated = false;
var cacheFile = fs.statSync(baseDir + '/cache/allModulesCode.js').mtime.getTime();
for (var j = 0; j < allDirs.length && mustUpdated == false; j++)
{
var files = fs.readdirSync(baseDir + '/' + allDirs[j]);
for (var i = 0; i < files.length; i++)
{
if (files[i].endsWith(".js"))
{
if (fs.statSync(baseDir + '/' + allDirs[j] + "/" + files[i]).mtime.getTime() >= cacheFile)
{
mustUpdated = true;
break;
}
}
}
}
}
if (!mustUpdated)
{
//response.write(fs.readFileSync(baseDir + '/cache/allModulesCode.js', "utf8"));
response.write(fs.readFileSync(baseDir + '/cache/allModulesCode.js.orig', "utf8"));
response.end();
return;
}
for (var j = 0; j < allDirs.length; j++)
{
var files = fs.readdirSync(baseDir + '/' + allDirs[j]);
for (var i = 0; i < files.length; i++)
{
if (files[i].endsWith(".js"))
{
code += "n// ----------------------------n";
code += "// " + allDirs[j] + "/" + files[i] + "n";
nbLines += 4;
var data = fs.readFileSync(baseDir + '/' + allDirs[j] + "/" + files[i], "utf8");
var dataLines = data.split('n').length;
code += "codeLines[codeLines.length]={fromLine:" + nbLines + ",toLine:" + (nbLines + dataLines) + ",name:'" + allDirs[j] + "/" + files[i] + "'}n";
nbLines += dataLines;
code += "// ----------------------------n";
code += data;
}
}
}
code += "nn// ----------------------------n";
code += "// images datesn";
code += "// ----------------------------n";
code += "var imageVersion={};n";
var files = fs.readdirSync(baseDir + '/images');
for (var i = 0; i < files.length; i++)
{
var s = fs.statSync(baseDir + '/images/' + files[i]);
code += "imageVersion['" + files[i] + "']='" + s.mtime.getTime() + "';n";
}
code += "n// ----------------------------n";
code += "// Initn";
code += "initialize();";
var UglifyJS = require("uglify-js");
fs.writeFile(baseDir + '/cache/allModulesCode.js.orig', code+"nncodeStyle='orig'n", "utf8");
var result = UglifyJS.minify(code+"nncodeStyle='mini'n", {fromString: true});
var miniCode = result.code;
fs.writeFile(baseDir + '/cache/allModulesCode.js', miniCode, "utf8");
response.write(code+"nncodeStyle='orig'n");
//response.write(miniCode);*/
response.end();
}
function cssCode(filename, response)
{
//fs.createReadStream(filename).pipe(response);
//console.log(filename)
fs.readFile(filename, "utf8", function (err, fileData)
{
fileData = fileData;
var files = fs.readdirSync(baseDir + '/images');
for (var i = 0; i < files.length; i++)
{
var r = new RegExp(files[i].replace(".", "\."), "g");
var s = fs.statSync(baseDir + '/images/' + files[i]);
fileData = fileData.replace(r, files[i] + "?v=" + s.mtime.getTime());
}
//console.log(fileData)
response.write(fileData);
response.end();
});
}
function mainFile(request, response)
{
var filename = path.join(baseDir, "/index.html");
//console.log(filename);
fs.readFile(filename, function (err, fileData)
{
response.writeHead(200, { "Content-Type": "text/html", "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache" });
var worldGenModules = [];
for (var j = 0; j < worldGenModuleDirs.length; j++)
{
var files = fs.readdirSync(baseDir + '/' + worldGenModuleDirs[j]);
for (var i = 0; i < files.length; i++)
{
if (files[i].endsWith(".js"))
{
worldGenModules[worldGenModules.length] = worldGenModuleDirs[j] + files[i];
//modules[modules.length] = worldGenModuleDirs[j] + files[i];
}
}
}
//response.write(("" + fileData).replace("#title#", config.title).replace("'#modules#'", JSON.stringify(modules)).replace("'#worldGenModules#'", JSON.stringify(worldGenModules)));
response.write(("" + fileData).replace("#title#", config.title).replace("'#worldGenModules#'", JSON.stringify(worldGenModules)));
response.end();
});
}
function sortByDate(a, b)
{
if (a.date < b.date)
return 1;
if (b.date < a.date)
return -1;
return 0;
}
/*function manifestFile(request, response)
{
response.writeHead(200, { "Content-Type": "text/cache-manifest", "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache" });
var dirs = [];
dirs.append(moduleDirs);
dirs.append(worldGenModuleDirs);
dirs.append(["images/"]);
var maxfs = 0;
for (var j = 0; j < dirs.length; j++)
{
//console.log(baseDir + "/" + dirs[j])
var files = fs.readdirSync(baseDir + "/" + dirs[j]);
for (var i = 0; i < files.length; i++)
{
var s = fs.statSync(baseDir + '/' + dirs[j] + files[i]);
var s = s.mtime.getTime();
if (s > maxfs)
maxfs = s;
}
}
response.write("CACHE MANIFESTn");
response.write("# Version " + s + "n");
for (var j = 0; j < dirs.length; j++)
{
//console.log(baseDir + "/" + dirs[j])
var files = fs.readdirSync(baseDir + "/" + dirs[j]);
for (var i = 0; i < files.length; i++)
{
var s = fs.statSync(baseDir + '/' + dirs[j] + files[i]);
var s = s.mtime.getTime();
if (s > maxfs)
maxfs = s;
}
}
response.write("/index.htmln");
response.write("/socket.io/socket.io.jsn");
response.write("/lib/random.jsn");
response.write("/lib/perlin.jsn");
response.write("/main.jsn");
response.write("/allModulesCode.jsn");
for (var j = 0; j < dirs.length; j++)
{
//console.log(baseDir + "/" + dirs[j])
var files = fs.readdirSync(baseDir + "/" + dirs[j]);
for (var i = 0; i < files.length; i++)
{
if (files[i].endsWith(".css"))
response.write('/' + dirs[j] + files[i] + 'n');
}
}
var files = fs.readdirSync(baseDir + "/images");
for (var i = 0; i < files.length; i++)
{
var s = fs.statSync(baseDir + '/images/' + files[i]);
var s = s.mtime.getTime();
response.write('/images/' + files[i] + '?v=' + s + 'n');
}
response.end();
}*/
function welcomeFile(request, response)
{
var filename = path.join(baseDir, "/welcome.html");
//console.log(filename);
fs.readFile(filename, function (err, fileData)
{
response.writeHead(200, { "Content-Type": "text/html", "Expires": -1, "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache" });
var db = GLOBAL.getDb();
db.open(function (err, db)
{
if (db == null)
{
fileData = ("" + fileData).replace("#news#", "");
response.write(fileData.replace("#top#", ""));
return;
}
db.collection("news", function (err, collection)
{
collection.find().toArray(function (err, data)
{
var news = "<ul>";
data.sort(sortByDate);
for (var i = 0; i < data.length && i < 5; i++)
news += "<li><b>" + data[i].date + ":</b> " + data[i].text + "</li>";
news += "</ul>";
fileData = ("" + fileData).replace("#news#", news);
db.collection("top", function (err, collection)
{
if (collection == null)
{
response.write(fileData.replace("#top#", ""));
response.end();
db.close();
return;
}
collection.findOne({_id: "user"}, function (err, data)
{
if (data == null)
{
response.write(fileData.replace("#top#", ""));
response.end();
db.close();
return;
}
var top = "<table>";
top += "<tr><td>Best players:</td><td>Level:</td></tr>";
for (var i = 0; i < data.level.length && i < 15; i++)
{
top += "<tr><td>" + data.level[i].username + "</td><td>" + data.level[i].value + "</td></tr>";
}
top += "</table>";
response.write(fileData.replace("#top#", top));
response.end();
db.close();
return;
});
});
});
});
});
});
}
function socketHandler(socket)
{
GLOBAL.sockets[GLOBAL.sockets.length] = socket;
socket.playerId = nextPlayerId++;
socket.pingDate = new Date();
socket.broadcast.emit('player_connect', {playerId: socket.playerId});
socket.emit('player_id', {playerId: socket.playerId});
for (var i = 0; i < GLOBAL.socketFunctions.length; i++)
eval("socket.on(GLOBAL.socketFunctions[" + i + "].name,function (data) { GLOBAL.socketFunctions[" + i + "].action(socket,data); });");
}
function socketPositionUpdate(socket, data)
{
//console.log("ID: "+data.playerId+", X: "+data.x+", Y: "+data.y+" Z: "+data.z);
// Send players within the areas
for (var i = 0; i < GLOBAL.sockets.length; i++)
{
if (GLOBAL.sockets[i].playerId == socket.playerId)
continue;
if (GLOBAL.sockets[i].position == undefined && Math.abs(data.ax) < 2 && Math.abs(data.ay) < 2)
{
GLOBAL.sockets[i].emit('player_position', data);
continue;
}
if (GLOBAL.sockets[i].position == undefined || GLOBAL.sockets[i].position.ax == null)
continue;
if (Math.abs(GLOBAL.sockets[i].position.ax - data.ax) > 1 || Math.abs(GLOBAL.sockets[i].position.ay - data.ay) > 1)
continue;
GLOBAL.sockets[i].emit('player_position', data);
}
socket.position = data;
for (var i = 0; i < GLOBAL.updatePositionFunctions.length; i++)
GLOBAL.updatePositionFunctions[i](socket, data);
}
function checkTimeout()
{
/*var now = new Date();
for (var i = 0; i < GLOBAL.sockets.length; i++)
{
var diff = (now - GLOBAL.sockets[i].pingDate) / 1000;
if (diff > 60 && GLOBAL.sockets[i].username != null && GLOBAL.sockets[i].username != undefined)
{
GLOBAL.sockets[i].emit('close_duplicate', {});
GLOBAL.sockets[i].disconnect('unauthorized');
}
}*/
}
app.listen(config.port);

配置.js

var config = {
dbName: "cubicverse",
port: 80,
title: "Cubicverse - Early Access",
secureKey: "HjkhsdhsklKsha9i1390s"
};
module.exports = config;

对于当前正在运行的服务器.js进程实例,Ubuntu 家用计算机的sudo netstat -tulpn输出为:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      1423/mysqld     
tcp        0      0 127.0.0.1:5940          0.0.0.0:*               LISTEN      1679/teamviewerd
tcp        0      0 127.0.1.1:53            0.0.0.0:*               LISTEN      10923/dnsmasq   
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      1362/postgres   
tcp        0      0 127.0.0.1:5433          0.0.0.0:*               LISTEN      1361/postgres   
tcp        0      0 0.0.0.0:27036           0.0.0.0:*               LISTEN      25647/steam     
tcp        0      0 127.0.0.1:57343         0.0.0.0:*               LISTEN      25647/steam     
tcp        0      0 0.0.0.0:58978           0.0.0.0:*               LISTEN      21401/skype     
udp        0      0 0.0.0.0:49828           0.0.0.0:*                           10923/dnsmasq   
udp        0      0 0.0.0.0:58233           0.0.0.0:*                           1103/avahi-daemon: 
udp        0      0 127.0.0.1:46077         0.0.0.0:*                           21401/skype     
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           10888/libpepflashpl
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           1103/avahi-daemon: 
udp        0      0 0.0.0.0:58978           0.0.0.0:*                           21401/skype     
udp        0      0 0.0.0.0:27036           0.0.0.0:*                           25647/steam     
udp        0      0 0.0.0.0:56039           0.0.0.0:*                           25647/steam     
udp        0      0 127.0.1.1:53            0.0.0.0:*                           10923/dnsmasq   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           18145/dhclient  
udp        0      0 0.0.0.0:631             0.0.0.0:*                           10911/cups-browsed
udp6       0      0 :::5353                 :::*                                10888/libpepflashpl
udp6       0      0 :::5353                 :::*                                1103/avahi-daemon: 
udp6       0      0 :::44104                :::*                                1103/avahi-daemon: 
udp6       0      0 :::44570                :::*                                10923/dnsmasq   

在 Ubuntu 服务器上:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      1476/mongod     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      32567/sshd      
tcp6       0      0 :::80                   :::*                    LISTEN      19531/node      
tcp6       0      0 :::22                   :::*                    LISTEN 

Iptables 和 ufw 在本地计算机上均已关闭:

peter@peter-HP-Notebook:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
peter@peter-HP-Notebook:~$ sudo ufw status
Status: inactive

Ubuntu 服务器上的服务器进程输出:

root@ubuntu-2gb-nyc3-01:~/cubicverse-newer/server# forever server.js
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
(node:19531) DeprecationWarning: process.EventEmitter is deprecated. Use require('events') instead.
(node:19531) DeprecationWarning: 'GLOBAL' is deprecated, use 'global'

在家用 Ubuntu PC 上:

peter@peter-HP-Notebook:~/cubicverse-new/server$ node server.js
(node:30406) DeprecationWarning: process.EventEmitter is deprecated. Use require('events') instead.
(node:30406) DeprecationWarning: 'GLOBAL' is deprecated, use 'global'

我尝试在家用 Ubuntu 计算机上以提升的权限运行该过程,并获得:

sudo node server.js
[sudo] password for peter: 
/home/peter/cubicverse-new/server/node_modules/socket.io/lib/store.js:35
Store.prototype.__proto__ = EventEmitter.prototype;
TypeError: Cannot read property 'prototype' of undefined
at Object.<anonymous> (/home/peter/cubicverse-
new/server/node_modules/socket.io/lib/store.js:35:41)

有趣的是,这与我在家用 Ubuntu 机器上降级节点版本之前遇到的错误相同。

关于可能导致这种情况的原因的任何猜测?

我更改了EventEmitter.prototype的所有实例,改为使用require('events')。然后我将我的节点版本从版本 6.9.1 更新回 7.10.0,我将其降级为(可能不是必需的,但无论如何都值得这样做)并以 root 身份再次运行服务器进程。

现在一切正常。

最新更新