How to make Apache and Node.js with Socket.io setu

2019-02-06 16:37发布

问题:

Just starting with Node.js/Socket.io. Ultimately I want to serve the pages from Apache while pushing and augmenting some of the content with Node.js server. This is just a little test to see how it all works. Here is my setup:

  • Apache running on port 8080
  • Node.js running on port 8000

I copied the index.html page (see below) to their respective root directories.

  1. When I open http://localhost:8000 everything works as expected and I can see the complete message exchange.

  2. When I open http://localhost:8080 everything appears to work (based on request and response headers, and Node.js log compared to 1.) but I can see no message exchange in either Node.js or Firebug log.

  3. When I first open the page served by Node.js, close it, then open the page served by Apache it works. I can see "CONNECTED", "DISCONNECTED", and then "CONNECTED" messages in the Node.js terminal.

The question is: how to make case 2. work?

Page:

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script>
    var socket = io.connect('http://localhost:8000');
    socket.on('server calling', function(data) {
        console.log(data);
        socket.emit('client response', {my : 'data'});
    }); 
    socket.emit('client calling', {foo : 'bar'});
</script>
Hello!

Server:

var app = require('http').createServer(handler);
var io = require('socket.io').listen(app);
var fs = require('fs');

app.listen(8000);

function handler(req,res) {  

    path = req.url == "/" ? "./index.html" : "." + req.url; 
    fs.readFile(path,
        function(err, data) {
            if(err) {
                res.writeHead(500);
                return res.end('Error loading page.');
            }   
            res.writeHead(200);
            res.end(data);
        }   
    );

    io.sockets.on('connection', function (socket) {

        console.log('CONNECTED');

        setInterval(function() {            
            socket.emit('server calling', { hello: 'world' }); 
        }, 2000);

        socket.on('client response', function(data) {
            console.log(data);
        });
        socket.on('disconnect', function() {
            console.log('DISCONNECTED');
        }); 
        socket.on('client calling', function(data) {
            console.log(data);
        }); 
    });
};

I'm aware of the following questions on SO:

  • Node.js + Socket.io + Apache
  • node.js and apache on different servers

but I still cannot make it work...

I've tried:

  • "change the path to /socket.io-client/dist/socket.io.js"

In the browser: ReferenceError: io is not defined. When I go to http://localhost:8000/socket.io-client/dist/socket.io.js I get Welcome to socket.io. response.

In the server log: info - unhandled socket.io url

  • "serve the socket.io.js from your Apache static server"

How would that work? Apache does not know how to handle the /socket.io/socket.io.js and node_modules automagic?

  • dark_ruby suggested setting up a proxy

I changed the script source in the index.html page in Apache root directory to:

<script src="http://localhost:8080/socket.io/"></script>

In Apache config, I added:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyPass /socket.io/ http://localhost:8000/socket.io/socket.io.js

With such configuration opening http://localhost:8080 had the same result as in 2. above:

$ node node-server.js
   info  - socket.io started
   debug - served static content /socket.io.js
   debug - client authorized
   info  - handshake authorized U9xPRw_0rRpsv-K9qVkS
   debug - setting request GET /socket.io/1/websocket/U9xPRw_0rRpsv-K9qVkS
   debug - set heartbeat interval for client U9xPRw_0rRpsv-K9qVkS
   debug - client authorized for 
   debug - websocket writing 1:: 
   debug - emitting heartbeat for client U9xPRw_0rRpsv-K9qVkS
   debug - websocket writing 2:: 
   debug - set heartbeat timeout for client U9xPRw_0rRpsv-K9qVkS
   debug - got heartbeat packet
   debug - cleared heartbeat timeout for client U9xPRw_0rRpsv-K9qVkS
   debug - set heartbeat interval for client U9xPRw_0rRpsv-K9qVkS
   ... 
   info  - transport end (undefined)
   debug - set close timeout for client U9xPRw_0rRpsv-K9qVkS
   debug - cleared close timeout for client U9xPRw_0rRpsv-K9qVkS
   debug - cleared heartbeat interval for client U9xPRw_0rRpsv-K9qVkS
   debug - discarding transport

i.e. no messages.

回答1:

Your io.sockets is located inside handler function. I'm assuming it will be called when you make a request to node JS server. Till then, node JS server never executes your IO code.

Try moving it out of the handler and add it in your app.js.

And no need to change the path or the proxy. The code you posted originally is just fine. The problem is not with loading socket.io.js file. But node server detecting io events.