18

diagnosis.pyリアルタイムのイベントベースのデータを生成する Python スクリプトがあります。Node.js を使用すると、それを子プロセスとして起動してその出力をキャプチャし、Socket.IO を使用してそれをクライアントに送信し、HTML を使用して表示できます。

サーバ

var util  = require('util'),
    spawn = require('child_process').spawn,
    ls    = spawn('python', ['diagnosis.py']);

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {
    ls.stdout.on('data', function (gdata) {
      socket.emit('news', gdata.toString());
    });
});

クライアント

<html>
    <head>
        <script src="/socket.io/socket.io.js"></script>
        <script>
          var d = "";
          var socket = io.connect('http://localhost');
          socket.on('news', function (data) {
            d += data;
            document.getElementById('data').innerHTML = d;
            console.log(data);
          });
        </script>
    </head>
    <body>
        <div id="data"></div>
    </body>
</html>

質問

これは素晴らしいことですが、Socket.IO が提供するのと同じ HTML-Node.js 通信機能を探している場合はどうでしょうか。どうやってそれをしますか?そこにはWebサーバーがないため、Socket.IOはあまり意味がなく、ベアTCPを介した通信は同じパワー/エレガンスを提供しません. Node.js と Python の間で全二重通信を実現するにはどうすればよいですか?

ここに画像の説明を入力

更新私は自分の質問に答えましたが、別のアプローチを受け入れます。RPC は、私が望むことを完全には行いません。

4

4 に答える 4

8

Apache Thriftは、すべての主要言語間で RPC コードを作成するための非常に優れた方法です。タイプとサービスを宣言する一般的な Thrift 仕様を作成すると、コード ジェネレーターが目的の言語のバインディングを作成します。ノードと Python コード ベースの間でメソッドを呼び出すための API を使用できます。

より一般的な低レベルのアプローチでは、ZeroMQはすべての主要言語もサポートするメッセージ キュー ライブラリです。これにより、(純粋な RPC だけでなく) 通信方法について独自のソリューションを設計できます。リクエスト/リプライ、プッシュ/プル、パブ/サブ、ペアのパターンがあります。あらゆるタイプのスケーラブルなシステムをまとめるのに十分なツールを提供します。

私は両方を使用しましたが、それらは優れたソリューションです。

非常に大まかな例として、Thrift 仕様はこのようなものかもしれません。Python から node.js にイベントを通信し、それを処理して何らかの応答を返したいとしましょう。

myspec.thrift

struct Event {
    1: string message; 
}

service RpcService {
    string eventOccurred(1:Event e)
}

Eventこれは、メッセージを保持する単一の文字列メンバーで呼び出されるデータ構造を定義します。次に、呼び出されたサービスが、 を引数として期待RpcServiceする 1 つの関数を定義し、文字列を返します。eventOccuredEvent

このコードを python および node.js 用に生成すると、python 用のクライアント側コードと node.js 用のサーバー側コードを使用できます。

パイソン

from myrpc import RpcService, ttypes

# create a connection somewhere in your code
CONN = connect_to_node(port=9000)

def someoneClickedSomething():
    event = ttypes.Event("Someone Clicked!")
    resp = CONN.eventOccurred(event)
    print "Got reply:", resp

node.js

// I don't know node.js, so this is just pseudo-code

var thrift = require('thrift');
var myrpc = require('myrpc.js');

var server = thrift.createServer(myrpc.RpcService, {
  eventOccurred: function(event) {
    console.log("event occured:", event.message);
    success("Event Processed.");
  },
});
server.listen(9000);
于 2012-12-12T21:36:22.987 に答える
2

この質問に触発されたライブラリを使用しdiagnosis.pyて、Socket.IO クライアントに変えました。このようにして、リアルタイム データを Node.js Socket.IO サーバーに送信できます。

socketIO.emit('gaze', ...)

そして、socket.broadcast.emitすべての Socket.IO クライアント (ブラウザとdiagnosis.py) にデータを送信するようにします。

RPC は言語間開発のより標準的なアプローチかもしれませんが、目標がデータ交換である場合、それを行うのは少しやり過ぎだと思います。また、すぐに使用できるイベント IO もサポートしていません。

2013年1 月の更新socket.broadcast.emit多くの不要なトラフィックが生成されるため、これを行うためのより良い方法を見つけようとしました。私が思いついた解決策は、前述の基本的な python Socket.IO クライアント ライブラリでサポートされている名前空間を使用することです。

パイソン

self.mainSocket = SocketIO('localhost', 80)
self.gazeSocket = self.mainSocket.connect('/gaze')
self.gazeSocket.emit('gaze', ...)

視線の名前空間に接続します。

Node.js

var gaze = io.of('/gaze').on('connection', function (socket) {
    socket.on('gaze', function (gdata) {
        gaze.emit('gaze', gdata.toString());
    });
});

これは、gaze 名前空間に接続されたクライアントにのみ受信したデータを送信します。

ブラウザ

var socket = io.connect('http://localhost/gaze');
socket.on('gaze', function (data) {
    console.log(data);
});
于 2012-12-13T23:21:20.840 に答える
1

ソケットの上に単純なプロトコルを提供するものを探しているだけで、メッセージのバッファリングや区切りなどすべてを処理する必要がない場合は、2 つの明白な選択肢 (データの種類によって異なります)再送信しようとしている) はネット文字列と JSON-RPC です。どちらの言語でも、ライブラリには複数の選択肢がありますが、最終的には次のような単純なコードにすることができます。

class MyService(Service):
    # … code to set up the newsdb
    def getnews(self, category, item):
        return self.newsdb.get(category, item)
myService = MyService(6000)

myService = Service(6000)
// … code to set up the newsdb
myService.getnews = function(category, item, callback) {
    callback(this.newsdb.get(category, item);
}
于 2012-12-12T21:42:23.957 に答える