Node.js + Socket.io + Apache

Posted

技术标签:

【中文标题】Node.js + Socket.io + Apache【英文标题】: 【发布时间】:2011-12-02 16:45:32 【问题描述】:

我正在寻找一种通过以下方式集成 的方法: 我希望 apache 继续提供 html / JS 文件。 我想让 node.js 监听端口 8080 上的连接。像这样:

var util = require("util"),
    app = require('http').createServer(handler),
    io = require('/socket.io').listen(app),
    fs = require('fs'),
    os = require('os'),
    url = require('url');

app.listen(8080);

function handler (req, res) 

    fs.readFile(__dirname + '/index.html',
  function (err, data) 
    if (err) 
      res.writeHead(500);
      return res.end('Error loading index.html');
    

    res.writeHead(200);
    res.end(data);
  );


io.sockets.on('connection', function (socket) 
  socket.emit('news',  hello: 'world' );

  socket.on('my other event', function (data) 
    socket.emit('ok 1',  hello: 'world' );
  );

  socket.on('clientMSG', function (data) 
    socket.emit('ok 2',  hello: 'world' );
  );

);

如果我访问连接到此服务器的 HTML,它可以工作,但我需要访问 mydomian.com:8080/index.html。 我想要的是能够访问 mydomian.com/index.html。并能够打开一个套接字连接:

<script>
        var socket = io.connect('http://mydomain.com', port: 8080);
        socket.on('news', function (data) 
            console.log(data);
            socket.emit('my other event',  my: 'data from the client' );
        );

        socket.on('connect', function (data) 
            console.log("connect");
        );

        socket.on('disconnect', function (data) 
            console.log("disconnect");
        );


            //call this function when a button is clicked
        function sendMSG()
        
            console.log("sendMSG"); 
            socket.emit('clientMSG',  msg: 'non-scheduled message from client' );
        

    </script>

在这个例子中,当我转到 URL 中的 8080 端口时,我不得不使用 fs.readFile 。

有什么建议吗?谢了。

【问题讨论】:

尝试使用 nginx 而不是 apache,特别是如果您只想提供静态文件。 Apache 为每个请求启动一个新线程,这部分违背了使用节点的理念/原因。 【参考方案1】:

从 Apache 端口 80 提供静态内容,并通过端口 8080 上的 Socket.IO 服务器提供动态/数据内容。您的 Socket.IO 应用中不需要 app = require('http').createServer(handler)

Apache 80 端口 |-------------|客户|------------| Socket.IO端口8080

var io = require('socket.io').listen(8080);

io.sockets.on('connection', function (socket) 
  io.sockets.emit('this',  will: 'be received by everyone');

  socket.on('clientMSG', function (from, msg) 
    console.log('I received a private message by ', from, ' saying ', msg);
  );

  socket.on('disconnect', function () 
    sockets.emit('user disconnected');
  );
);

【讨论】:

感谢您的回复。我做了更改,现在看起来客户端没有获取 /socket.io/socket.io.js 文件。这个文件是由 Node 中的 HTTP 服务器提供的吗? 我搞定了。将路径更改为 /socket.io-client/dist/socket.io.js 谢谢! 是的,您需要在端口 80 上从您的 Apache 静态服务器提供 socket.io.js 并执行类似 的操作您的客户端代码 idk 如果这会有所帮助,但如果你在当前目录中 npm install socket.io,在 :8888 运行应用程序,你需要编写脚本 src="mydomain:8888/socket.io/socket.io.js",即使它是在 node_modules/socket.io/lib/socket.io.js 这不会触发“同源策略”违规吗? en.wikipedia.org/wiki/Same_origin_policy【参考方案2】:

AWS + APACHE + NODEJS + SOCKET.IO + ANGULARJS

服务器端 这适用于我在端口 80 和 NodeJS 上运行 apache 的生产服务器 在端口 8000 上。通过您想要的选项更改 NodeJS 端口...

    在 /var/www/html 为 NodeJS 服务器的文件创建一个名为“nodejs”的文件夹 在不同于 80 的端口上运行 Nodejs,例如端口 8000 执行命令:a2enmod proxy_http 执行命令:a2enmod proxy_wstunnel

    将接下来的 2 行放在以下文件的末尾:/etc/apache2/apache2.conf

    LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
    LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so 
    

    将接下来的 12 行放在以下文件的末尾:/sites-available/000-default.conf (如果您创建了其他网站,请将这些行放在那里)

    RewriteEngine On
    RewriteCond %REQUEST_URI  ^socket.io          [NC]
    RewriteCond %QUERY_STRING transport=websocket [NC]
    RewriteRule /.*       ws://localhost:8000/$1  [P,L]
    
    RewriteCond %HTTP:Connection Upgrade [NC]
    RewriteRule /(.*) ws://localhost:8000/$1 [P,L]
    
    ProxyPass /nodejs http://localhost:8000/
    ProxyPassReverse /nodejs http://localhost:8000/
    
    
    ProxyPass /socket.io http://localhost:8000/socket.io
    ProxyPassReverse /socket.io http://loacalhost:8000/socket.io
    
    ProxyPass /socket.io ws://localhost:8000/socket.io
    ProxyPassReverse /socket.io ws://localhost:8000/socket.io
    

    sudo service apache2 重启

客户端 我使用以下library 在 AngularJS 中实现 Socket.io,但是 我认为本指南对于 socket.io 技术的基本 javascript 实现也很有用。

调用我的 php 服务器:example.com 调用 NodeJS 服务器:example.com/nodejs 调用 NodeJS Socket:example.com

希望能帮到你!

【讨论】:

谢谢,我能够解决在 apache 服务器上运行 socket.io 的问题。 使用您的出色答案和其他研究,您可以在此处找到带有 certbot、CORS 标头和解释的完整示例(如果没有您的建议,我无法做到!):***.com/questions/9831594/…【参考方案3】:

您可以继续从 Apache 提供页面,但您需要在 node.js/socket.io 中启用 CORS:

index.html(由 Apache 提供)

<script src = "https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.0/socket.io.js"></script>
<script>
   const socket = io("ws://your.domain.com:8080");
<script>

app.js(在 nodejs 中):(启用 CORS)

const express = require('express');
const app = express();
const http = require('http').Server(app);
const io = require('socket.io')(http, 
    cors: 
      origin: "*",
      methods: ["GET", "POST"]
    
);

http.listen(8080);

【讨论】:

以上是关于Node.js + Socket.io + Apache的主要内容,如果未能解决你的问题,请参考以下文章

HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket

Node.js 和 socket.io 的混淆

Node.js socket.io.js 未找到或 io 未定义

找不到Node.js /socket.io/socket.io.js express 4.0

node.js + socket.io:拍卖网站开发

Heroku 上的 socket.io + node.js