簡體   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