繁体   English   中英

使用PHP和Node.js的Websocket

[英]Websockets with PHP and Node.js

是否可以让PHP脚本通过websockets将数据发送到Node.js服务器?

我正在计划一个将在后台运行PHP脚本并运行一些魔术的最终项目,而最终用户将使用的前端应用程序将在Node.js中。 仅在Node.js中会有一些socket.io交互,但我希望能够从PHP脚本将数据推送到socket.io。

答案是肯定的,但是确切的实现取决于您的环境/要求。

这是我从最近的一个项目中窃取的一个示例:它发送一条消息,然后等待响应以chr(10)(“ \\ n”)结尾。 必须在0.5秒内收到该响应,否则将认为失败(请参阅时序循环)。 您可以根据需要摆弄这些位。

注意:$ 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);
        }

我也在做这个。 我的实现与其他实现略有不同。 大多数人使用php&curl + nodejs&express&socketio

我已经通过以下方式做到了:

  • php和nodejs中的内存缓存(共享用户名和cookie)(您也可以使用redis)
  • 一个自定义的PHP类,用于通过websocket向本地主机发送请求,在该主机上,nodejs服务器广播到用户室(来自同一用户的所有会话)。

是我用来从php到socketio进行通信的类(仅将数据发送到nodejs,而不发送消息!)

当我连接到socket.io时,我的脚本读取我的php cookie并将其发送到节点服务器,在该节点服务器中它访问memcache json会话并识别用户,并将他加入房间。

是一个php json序列化的memcached会话处理程序类。 它与我使用的类似。

要在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;

当来自本地主机的(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 ); }
});

如果我想将数据从node传递到php,我只需在nodejs服务器上执行php代码。 像这样:

 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