2013-07-11 10 views
6

私はを書きました。ピアツーピアルーター(スーパーノード)のように動作するTCP中継サーバーです。2つのTCPソケット間のカーネルベース(Linux)データ中継

最も単純なケースされ、それらの間に2つ開けソケットとデータ中継:

クライアントA < --->サーバー< ---> clientBサーバは約2000、このようなABにサービスを提供する必要があるしかし

ペア、すなわち。 4000個のソケット... ユーザランドにおける2つのよく知られているデータストリーム中継実装があり

socketA.recv()に基づいて、 - > socketB.send()socketB.recv() - > socketA.send()):

スレッドの使用/ ポーリング機能(非ブロッキング方式)
  • を選択の使用
    • /フォーク(ブロック法)

    スレッドを使用したので、最悪の場合、サーバーは2 * 2000スレッドを作成します。私はスタックのサイズを制限しなければならなかった、それは動作しますが、それは正しい解決策ですか?私の質問の

    コア:

    はユーザランドで2つのソケットの間で中継アクティブなデータを回避する方法はありますか?

    受動的な方法があるようです。たとえば、各ソケットからファイル記述子を作成し、2つのパイプを作成し、dup2()を使用することができます。stdin/outリダイレクトの場合と同じ方法です。その後、2つのスレッドはデータ中継には役に立たず、終了/終了することができます。 問題は、サーバがソケットとパイプを閉じなければならない場合、そしてその事実を記録するためにパイプが壊れたときを知る方法は?

    私は「ソケットペア」も見つけましたが、私の目的はわかりません。

    ユーザランドの負荷を軽減し、スレッドの量を制限するためにどのような解決策を提案しますか?

    いくつかの余分な説明:

    • サーバは(ID_Bと例えばID_A - ペア識別子。)、スタティックルーティングテーブルを定義しています。クライアントAはサーバーに接続し、ID_Aを送信します。次に、サーバーはクライアントBを待ちます。AとBがペアになっている(両方のソケットがオープンされている)と、サーバーはデータ・リレーを開始します。
    • クライアントは対称型NATの背後にある単純なデバイスなので、N2NプロトコルまたはNATトラバーサル技術は複雑すぎます。

    ゲルハルト・リーガーのおかげで、私はヒントがあります:

    私はRECV/ ユーザ空間で送信、読み取り/書き込みを避けるための2つのカーネル空間の方法を知っています:

    • sendfile
    • スプライス

    どちらにもファイル記述子のタイプに関する制限があります。

    dup2は、カーネルAFAIKで何かをするのに役立ちません。

    マンページ:splice(2)splice(2)vmsplice(2)sendfile(2)tee(2)

    関連リンク:

  • +1

    多くの接続では、いくつかのスレッドと['epoll(4)'](http://linux.die.net/man/4/epoll)の組み合わせが役に立つでしょう。 –

    +1

    それで、あなたは[libev](http://software.schmorp.de/pkg/libev.html)のようなものを使うことができました – Hasturkun

    +0

    ありがとう。しかしそれはまだユーザーランドでアクティブなリレーです。受動的な方法が存在すると私は信じている。サーバは5秒間のタイムアウトでクライアントのIDを待っているので、スレッドはペアリングの段階で自然に選択されたようです。 – nopsoft

    答えて

    3

    hereを説明した説明、私は」 dスレッドでは決して行かない。特定の場所でのみ中断することができない場合よりいつでもどこでも中断することができるようにすることは、常に高価なため、スタックとスイッチングのオーバーヘッドが最も高くなります。 epoll()とスプライス(あなたのソケットがTCPの場合はそうです)を使うだけで、うまくいくでしょう。一度だけあなたのfdsを登録するイベントトリガーモードでもepollを動作させることができます。

    スレッドを絶対に使用する場合は、CPUコアごとに1つのスレッドを使用して負荷を分散させますが、これを行う必要がある場合、アフィニティ、各CPUソケットのRAMの位置など..あなたの質問には当てはまらない重要な役割を果たします。だから私はあなたのケースでは1つのスレッドが十分であると仮定しています。

    +0

    ありがとうございます。 EPOLLONESHOTやADD/DELを使う方が良いでしょうか? http://stackoverflow.com/questions/4173024/question-about-epoll-and-spliceやhttp://rg4.net/archives/375.htmlのように? – nopsoft

    +0

    EPOLLONESHOTを試したことはありませんが、EPOLLETの代わりに役立つかもしれません。私が思う複雑さを制限し、必要に応じて後で最適化を試みるために標準ADD/DELから始めます。 –