Send message from PHP directly to Node using socke

2019-08-25 19:07发布

问题:

I got a connection between PHP and Node using Redis working fine, but I'm intrigued by doing it without any external libraries and services and just with sockets.

I'm not sure on how much performance will suffer without having Redis in the middle, but for simpler projects, this would be nice with lesser code.

I got most of the code from this answer in Using PHP with Socket.io but I had to change some of the vars. But it's not working as expected.

I tried both with and without https, since I will be using https, but I tried making a simpler example with http just to get it working.

  • send.php creates and writes to a socket. I can confirm that it connects to node, since I get an error if node isn't running.
  • socket.js doesn't return anything in the console.logs.
  • socket-https.js returns connection from ::ffff:127.0.0.1 but isn't reading the socket.on('data'). What did I miss?

I think I misunderstand something in the var/require section in the http-version.

Can anyone spot why it's not working?

socket.js

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

var listener = app.listen(8080, function(){
    console.log('Listening on port ' + listener.address().port); 
});

http.on("connection", function(socket) {
    console.log("connection");
    if(socket.remoteAddress == "::ffff:127.0.0.1") {
        console.log("connection from " + socket.remoteAddress);
        socket.on('data', function(buf) {
            var js = JSON.parse(buf);
            console.log("on data: " + js); // Not working
        });
    }
});

socket-https.js

var fs = require('fs');
var privateKey  = fs.readFileSync('my-domain-com.key', 'utf8');
var certificate = fs.readFileSync('my-domain-com.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var app = require('express')();
var https = require('https').createServer(credentials, app);
var io = require('socket.io')(https);

https.listen(8080, function(){
  console.log('Server online');
});

https.on("connection", function(socket) {
    console.log("connection"); // Works!
    if(socket.remoteAddress == "::ffff:127.0.0.1") {
        console.log("connection from " + socket.remoteAddress); // Works!
        socket.on('data', function(buf) {
            var js = JSON.parse(buf);
            console.log("on data: " + js); // Not working :(
        });
    }
});

send.php

sio_message("Message","Data");

function sio_message($message, $data) {
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    $result = socket_connect($socket, '127.0.0.1', 8080);
    if(!$result) {
        die('cannot connect '.socket_strerror(socket_last_error()).PHP_EOL);
    } else {
        echo "Connected<br>";
    }
    $bytes = socket_write($socket, json_encode(Array("msg" => $message, "data" => $data)));
    echo " $bytes bytes written";
    socket_close($socket);
}

回答1:

Try this:

var fs = require('fs');
var privateKey  = fs.readFileSync('my-domain-com.key', 'utf8');
var certificate = fs.readFileSync('my-domain-com.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var app = require('express')();
var https = require('https').createServer(credentials, app);
var io = require('socket.io')(https);

https.listen(8080, function(){
  console.log('Server online');
});

io.on("connection", function(client) {
    client.on('join', function(data) {

        io.emit('message',{sendto: all, message: 'Hello there! Welcome!'});

    });
    client.on('message', function(data) {
        console.log(data);

        //forward this message to specific user
        io.emit('message',data);
    });
});

PHP Script:

$message = json_encode(Array("msg" => $message, "data" => $data));
$msg_length = strlen($message);
$bytes = socket_write($socket, $message, $msg_length);


回答2:

This might not have anything to do with the problem, but I did end up having to configure Apache to handle a Rewrite condition (I'm running Apache and Node.js side by side)

I figured I'd put the code here in case it helps anyone.

In httpd.conf I added the following code:

RewriteEngine On
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://localhost:8080%{REQUEST_URI} [P]

ProxyRequests Off
ProxyPass        /socket.io http://localhost:8080/socket.io retry=0
ProxyPassReverse /socket.io http://localhost:8080/socket.io retry=0

ProxyPass "/node" "http://localhost:8080/"

Maybe missing that is an issue? I'm not sure - also /node becomes a direct link to the node.js server.