同じマシン上の2つのアプリケーションを同じポートとIPアドレスにバインドできますか?さらに一歩進めて、一方のアプリが特定のIPからの要求を、もう一方のIPが別のリモートIPからの要求をリッスンできますか? 2つのスレッド(またはフォーク)から開始する1つのアプリケーションで同じような動作を実現できることはわかっていますが、共通点がない2つのアプリケーションでも同じことができますか?
TCPの場合、いいえ。一度に1つのアプリケーションだけが同じポートをlistenすることができます。 2つのネットワークカードを使用している場合は、1つのアプリケーションに同じポート番号を使用して最初のIPと2番目のIPをリッスンさせることができます。
UDP(Multicast)の場合、複数のアプリケーションが同じポートに加入できます。
はい(TCPの場合)プログラムがそうするように設計されていれば、2つのプログラムに同じソケットでlistenさせることができます。最初のプログラムでソケットが作成されたら、bind()
を実行する前に、ソケットにSO_REUSEADDR
オプションが設定されていることを確認してください。しかし、これはあなたが望むものではないかもしれません。これは着信TCP接続が両方ではなくプログラムのoneに向けられることである、それでそれは接続を複製しない、それはちょうど2つのプログラムが着信を処理することを許可要求。たとえば、Webサーバーはすべてポート80で待機している複数のプロセスを持ち、O/Sは新しい接続を受け入れる準備ができているプロセスに新しい接続を送信します。
SO_REUSEADDR
既にポートにバインドされているアクティブな待機ソケットがない限り、他のソケットがこのポートに対してbind()
を許可します。これにより、クラッシュ後にサーバーを再起動しようとしたときに、 "Address already in use"エラーメッセージを回避することができます。
原則として、いいえ。
それは石で書かれていません。しかし、それはすべてのAPIの作成方法です。アプリがポートを開き、そのハンドルを取得し、クライアント接続(またはUDPの場合はパケット)が到着すると、OSが(そのハンドルを介して)それを通知します。
OSが2つのアプリが同じポートを開くことを許可している場合、どのアプリがどのポートに通知するのかをどうやって知るのでしょうか。
しかし... ...それを回避する方法があります。
はい。
すべて同じポートにバインドされている複数の待機TCPソケットが、すべて異なるローカルIPアドレスにバインドされている場合、共存できます。クライアントは、必要な方に接続できます。これは0.0.0.0
(INADDR_ANY
)を除外します。
複数の承認済みソケットを共存させることができ、すべて同じ待機ソケットから受け入れ、すべて待機ソケットと同じローカルポート番号を示します。
すべて同じポートにバインドされた複数のUDPソケットは、(1)と同じ条件ですべて共存することも、バインド前にSO_REUSEADDR
オプションが設定されていることもあります。
TCPポートとUDPポートは異なるネームスペースを占有するため、TCPにポートを使用してもUDPへの使用が妨げられることはなく、その逆も同様です。
参照:Stevens&Wright、TCP/IP Illustrated、Volume II。
はいはい。私が覚えている限りでは、カーネルのバージョン3.9から(バージョンではわかりません)以降SO_REUSEPORT
のサポートが導入されました。最初のサーバーがソケットをバインドする前にこのオプションを設定している限り、SO_RESUEPORT
を使用すると、まったく同じポートとアドレスにバインドできます。
これはTCPとUDPの両方で機能します。詳しくはリンクを参照してください。 SO_REUSEPORT
注:私の意見では、受け入れられた答えはもはや当てはまりません。
いいえ。一度に1つのアプリケーションしかポートにバインドできません。バインドを強制した場合の動作は不定です。
マルチキャストソケットでは、SO_REUSEADDRが各ソケットのオプションで設定されている限り、複数のアプリケーションが1つのポートにバインドできます。
これを実現するには、すべての接続を受け入れて処理し、それらを同じポートで待機する必要がある2つのアプリケーションに渡します。多くのプロセスが80を監視する必要があるため、これはWebサーバーなどが採用するアプローチです。
これを超えて、私たちは詳細に入っています - あなたはTCPとUDPの両方にタグ付けしました、それはそれですか?また、どのようなプラットフォーム?
1つのアプリケーションが1つのネットワークインターフェースに対して1つのポートをリッスンすることができます。したがって、あなたは持つことができます:
httpd
はリモートからアクセス可能なインタフェースをリッスンしています。 192.168.1.1:80
127.0.0.1:80
をリッスンしています使用例としては、ロードバランサまたはプロキシとしてhttpd
を使用することが考えられます。
別の方法は、「本物の」サービスがリッスンしている別のポートに内部的にリダイレクトするトラフィックの種類(ssh、httpsなど)を分析する、あるポートでリッスンするプログラムを使用することです。
たとえば、Linuxの場合、sslh: https://github.com/yrutschle/sslh
TCP接続を作成するときは、特定のTCPアドレスに接続するように要求します。これは、使用しているプロトコルに応じて、IPアドレス(v4またはv6)の組み合わせです。 )とポート。
サーバが接続を待ち受けるとき、それは特定のIPアドレスとポート、すなわち1つのTCPアドレス、または各ホストのIPアドレス上の同じポート上で待ち受けたいことをカーネルに知らせることができます。 (通常はIPアドレス0.0.0.0
で指定されます)、事実上多くの異なる "TCPアドレス"(例えば192.168.1.10:8000
、127.0.0.1:8000
など)をリッスンしています。
いいえ、2つのアプリケーションが同じ「TCPアドレス」をリッスンすることはできません。メッセージが入ってくると、カーネルはどのアプリケーションにメッセージを渡すべきかをどのように認識するのでしょうか。
ただし、ほとんどのオペレーティングシステムでは、1つのインタフェースに複数のIPアドレスを設定できます(たとえば、インタフェースに192.168.1.10
がある場合、ネットワーク上に他の人が使用していなければ192.168.1.11
も設定できます)場合によっては、これら2つのIPアドレスのそれぞれで別々のアプリケーションがポート8000
をリッスンしている可能性があります。
少なくとも1つのリモートIPがすでに静的で、1つのアプリとのみ通信することがわかっている場合は、iptablesルール(table nat、chain PREROUTING)を使用して、このアドレスからの着信トラフィックを「共有」ローカルポートにリダイレクトします。適切なアプリケーションが実際に待機する他のポート。
はいといいえ。 1つのアプリケーションだけがポートをアクティブに待機できます。しかし、そのアプリケーションは他のプロセスへの接続を遅らせることができます。したがって、同じポート上で複数のプロセスが動作している可能性があります。
2つのアプリケーションが同じネットワークインターフェース上の同じポートをlistenするようにすることができます。
指定されたネットワークインタフェースとポートに対して待機するソケットは1つだけですが、そのソケットは複数のアプリケーション間で共有できます。
アプリケーションプロセス内に待機ソケットがあり、そのプロセスをfork
と継承した場合、技術的には2つのプロセスが同じポートを待機するようになります。
私はsocat
で次のことを試しました:
socat TCP-L:8080,fork,reuseaddr -
また、ソケットに接続していなくても、reuseaddr
オプションにもかかわらず、同じポートで2回リスンすることはできません。
このメッセージが表示されます(以前に予想されていました)。
2016/02/23 09:56:49 socat[2667] E bind(5, {AF=2 0.0.0.0:8080}, 16): Address already in use
@jnewtonが言ったことを共有するだけです。 Macでnginxと組み込みTomcatプロセスを開始しました。 8080で実行中の両方のプロセスを見ることができます。
LT<XXXX>-MAC:~ b0<XXX>$ Sudo netstat -anp tcp | grep LISTEN
tcp46 0 0 *.8080 *.* LISTEN
tcp4 0 0 *.8080 *.* LISTEN
アプリケーションによってあなたが複数のプロセスを意味するならば、はい、しかし一般にいいえ。たとえば、Apacheサーバーは同じポート(通常80)で複数のプロセスを実行します。実際にポートにバインドするプロセスの1つを指定し、そのプロセスを使用して接続を受け付けているさまざまなプロセスにハンドオーバーします。