简体   繁体   English

使用PHP和Node.js的Websocket

[英]Websockets with PHP and Node.js

Is it possible to have PHP scripts send data through to a Node.js server through websockets? 是否可以让PHP脚本通过websockets将数据发送到Node.js服务器?

I'm planning a side project that would have PHP scripts running in the background working some magic and the front end application that end users would use would be in Node.js. 我正在计划一个将在后台运行PHP脚本并运行一些魔术的最终项目,而最终用户将使用的前端应用程序将在Node.js中。 There would be some socket.io interaction just in Node.js but I'd like the ability to push data into socket.io from the PHP scripts. 仅在Node.js中会有一些socket.io交互,但我希望能够从PHP脚本将数据推送到socket.io。

The answer is yes, but exact implementation depends on your environment / requirements. 答案是肯定的,但是确切的实现取决于您的环境/要求。

Here is one example I've hacked from a recent project: it sends a message, then waits for a response to end in chr(10) ("\\n"). 这是我从最近的一个项目中窃取的一个示例:它发送一条消息,然后等待响应以chr(10)(“ \\ n”)结尾。 That response must be received within 0.5 seconds otherwise it assumes failure (see the timing loop). 必须在0.5秒内收到该响应,否则将认为失败(请参阅时序循环)。 You can fiddle with those bits as needed. 您可以根据需要摆弄这些位。

Note: $ip and $port need to be passed in. 注意:$ ip和$ port需要传递。

        $retval = false; // final return value will conatin something if it all works

        $socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false || !is_resource($socket)) {
            $socket = false;
            $this->lastErrorNum = socket_last_error();
            $this->lastErrorMsg = 'Unable to create socket: ' . socket_strerror(socket_last_error());
        } elseif (!@socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
            $this->lastErrorNum = socket_last_error($socket);
            $this->lastErrorMsg = 'Unable to set options on socket: ' . socket_strerror($this->lastErrorNum);
            @socket_clear_error ( $socket );
        } elseif (!@socket_connect($socket, $ip, $port)) {
            $this->lastErrorNum = socket_last_error($socket);
            $this->lastErrorMsg = 'Unable to connect socket: ' . socket_strerror($this->lastErrorNum);
            @socket_clear_error ( $socket );
        } else {
            // Socket connected - send message
            if (!@socket_write($socket, $message, strlen($message))) {
                $this->lastErrorNum = socket_last_error($socket);
                $this->lastErrorMsg = 'Unable to write to socket: ' . socket_strerror($this->lastErrorNum);
                @socket_clear_error ( $socket );
            } else {
                // Read a response
                $receiveStartTime = microtime(true);
                $response = '';
                socket_set_nonblock ($socket);
                while(microtime(true) - $receiveStartTime < 0.5) {
                    $n = @socket_recv($socket, $dataIn, 1024, 0);  // Assume max return value is 1024 bytes.
                    if ($n) {
                        $response .= $dataIn;
                    }
                    if (strpos($dataIn, "\n") !== false) {
                        @socket_clear_error ( $socket );
                        $response = str_replace("\n", '', $response);
                        break;
                    }
                }
                if (socket_last_error($socket) > 0) {
                    $this->lastErrorNum = socket_last_error($socket);
                    $this->lastErrorMsg = 'Unable to read from socket: ' . socket_strerror($this->lastErrorNum);
                    @socket_clear_error ( $socket );
                } else {
                    $retval = $response;
                }
            }
            @socket_close($socket);
        }

I am also working on this. 我也在做这个。 My implementation is a little different than others. 我的实现与其他实现略有不同。 Most people use php & curl + nodejs & express & socketio 大多数人使用php&curl + nodejs&express&socketio

I've done it the following way: 我已经通过以下方式做到了:

  • memcache in both php and nodejs (to share the userid and cookie) (you can also use redis) php和nodejs中的内存缓存(共享用户名和cookie)(您也可以使用redis)
  • a custom PHP class to send a request via websocket to localhost, where the nodejs server broadcasts to a user room (all sessions from the same user). 一个自定义的PHP类,用于通过websocket向本地主机发送请求,在该主机上,nodejs服务器广播到用户室(来自同一用户的所有会话)。

Here is the class I used to communicate from php to socketio (sends only data to nodejs and not the way around!) 是我用来从php到socketio进行通信的类(仅将数据发送到nodejs,而不发送消息!)

When I connect to socket.io, my script reads my php cookie and sends it to the node server, where it accesses the memcache json sessions and identifies the user, joining him to a room. 当我连接到socket.io时,我的脚本读取我的php cookie并将其发送到节点服务器,在该节点服务器中它访问memcache json会话并识别用户,并将他加入房间。

Here is a php json-serialized memcached session handler class. 是一个php json序列化的memcached会话处理程序类。 It is similar to the one I used. 它与我使用的类似。

To make a request in php --> socket.io i do the following: 要在php中发出请求-> socket.io,请执行以下操作:

$s = new SocketIO('127.0.0.1', 8088);

$adata = "On the other hand, we denounce with righteous indignation and dislike men who are so beguiled and demoralized by the charms of pleasure of the moment, so blinded by desire, that they cannot foresee the pain and trouble that are bound to ensue; and equal blame belongs to those who fail in their duty through weakness of will, which is the same as saying through shrinking from toil and pain.";

$msg = json_encode(array('event'=> 'passdata','data'=> $adata, 'to'=> 1));

$tr = 0;
$fl = 0;
for ($i = 0 ; $i < 1000; $i++) {
    $s->send( 'broadcast', $msg ) ? $tr++ : $fl++;
}
echo "HIT : " . $tr . PHP_EOL;
echo "MISS: " . $fl;

When a (socket.io) request from localhost goes to the server, i run this code: 当来自本地主机的(socket.io)请求转到服务器时,我运行以下代码:

var is_local = (this_ip === '127.0.0.1' ? true : false);
socket.on('broadcast', function(data) {
    if (data.length === 0 ) return;
    if (is_local && typeof data === 'string') {
        try {
            var j = JSON.parse(data);
        } catch (e) {
            console.log("invalid json @ broadcast".red);
            return false;
        }
        if (!j.hasOwnProperty('to') && !j.hasOwnProperty('event')) return false;
        io.to(j.to).emit(j.event, j.data);
        console.log('brc'.blue + ' to: ' + j.to + ' evt: ' + j.event);
        /** @todo remove disconnect & try to create permanent connection */
        socket.disconnect();
    } else { console.log('brc ' + 'error'.red ); }
});

If i want to pass data from node to php, I simply exec php code on my nodejs server. 如果我想将数据从node传递到php,我只需在nodejs服务器上执行php代码。 like this: 像这样:

 socket.on('php', function(func, data, callback) {
    /* some functions */
    if (check_usr(session) === false) return;
    console.log('php'.green + ' act:' + func);
    var cmd = 'php -r \'$_COOKIE["MONSTER"]="' + session + '"; require(\"' + __dirname + '/' + php_[func].exec + '\");\'';
    console.log(cmd);
    cp.exec(cmd ,
    function(err, stdout, stderr) { 
        if (err == null) {
            console.log(typeof callback);
            console.log(JSON.parse(callback));
            if (callback != null) callback(stdout);
            console.log(stdout);
            //socket.emit('php', {uid: uid, o: stdout});
            console.log('emitted');
        } else { 
            console.log('err '.red + stdout + ' ' + stderr);
        }
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM