私はを書きました。ピアツーピアルーター(スーパーノード)のように動作する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)
関連リンク:
- Understanding sendfile() and splice()
- http://blog.superpat.com/2010/06/01/zero-copy-in-linux-with-sendfile-and-splice/
- http://yarchive.net/comp/linux/splice.html(ライナス)
- C, sendfile() and send() difference?
- bridging between two file descriptors
- Send and Receive a file in socket programming in Linux with C/C++ (GCC/G++)
- http://ogris.de/howtos/splice.html
多くの接続では、いくつかのスレッドと['epoll(4)'](http://linux.die.net/man/4/epoll)の組み合わせが役に立つでしょう。 –
それで、あなたは[libev](http://software.schmorp.de/pkg/libev.html)のようなものを使うことができました – Hasturkun
ありがとう。しかしそれはまだユーザーランドでアクティブなリレーです。受動的な方法が存在すると私は信じている。サーバは5秒間のタイムアウトでクライアントのIDを待っているので、スレッドはペアリングの段階で自然に選択されたようです。 – nopsoft