【问题标题】:Websockets with PHP and Node.js使用 PHP 和 Node.js 的 Websocket
【发布时间】:2015-01-16 16:25:36
【问题描述】:

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

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

【问题讨论】:

  • socket.io 是硬性要求吗?或者可以使用核心net模块吗?
  • 不,这不是必需的,我可以让它工作的任何方式就足够了!
  • 你问的是 Websockets 还是 Socket.io?两者都被提及,但它们根本不一样。

标签: php node.js websocket


【解决方案1】:

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

我是通过以下方式完成的:

  • php和nodejs中的memcache(共享userid和cookie)(也可以使用redis)
  • 一个自定义 PHP 类,用于通过 websocket 向 localhost 发送请求,其中 nodejs 服务器向用户房间广播(来自同一用户的所有会话)。

Here 是我用来从 php 到 socketio 通信的类(只向 nodejs 发送数据,而不是反过来!)

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

Here 是一个 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;

当来自 localhost 的 (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 ); }
});

如果我想将数据从节点传递到 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);
        }
    });
});

【讨论】:

    【解决方案2】:

    答案是肯定的,但具体实施取决于您的环境/要求。

    这是我从最近的一个项目中破解的一个示例:它发送一条消息,然后等待响应以 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);
            }
    

    【讨论】:

      猜你喜欢
      • 2016-08-25
      • 1970-01-01
      • 2017-01-27
      • 1970-01-01
      • 2011-06-08
      • 2019-11-02
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多