QA@IT

TCP/IP通信に関する質問です。

4530 PV

下記の3つのLinuxPCを使って、TCP/IPによるソケット通信のシステムを作成しました。
PC1: IP:192.168.0.1 Port: 20000 TCPサーバ
PC2: IP:192.168.0.2 Port: 20000 TCPサーバ
PC3: IP:192.168.0.3 Port:ランダム(クライアントなので) TCPクライアント

PC3をクライアントとして、同じポート番号を持つアプリが動いている
PC1とPC2に繋いで通信をする形です。
このシステムは問題なく動きました。

しかし、続いてPC1とPC2を一つのPCに(ハードウェアとして)まとめたくなったときに、
下記の条件があったとき、どのようにすれば良いでしょうか?

  1. PC3のソフトウェアは一行も変更しない
  2. PC1とPC2のソフトは変更してもよいが、同一のハードウェアになっても、それぞれのソケットに流れるデータは変わらないようにすること

一台のコンピュータにおいて、一つのNICに複数のIPをふることはできましたが、
単一OS上で、同じポート番号のソケットを作成するのはできないと思っています。
今のところ、一台のコンピュータで仮想マシンを二台立ち上げる方法を考えていますが、
それ以外に上手い方法はあるでしょうか?

非常に困っているため、是非力を貸してもらえると幸いです。

回答

まずは、PC1とPC2で動いているソフトウェアがどのようにI.P.アドレスとポート番号をサーバソケットにバインド(bind)しているのかを確認しましょう。
Linuxであれば、netstat -na | grep ":20000" | grep "LISTEN"、
Windowsであれば、 netstat -na | find ":20000" | find "LISTEN"
で確認出来ます。
ローカル側のI.P.アドレスの部分が、以下のように

  • TCP 0.0.0.0:20000 0.0.0.0:0 LISTENING

「0.0.0.0:20000」となっている場合、I.P.アドレスを特定しないでバインドしている状態です。
上記と違い、ローカル側のI.P.アドレスの部分が、以下のように

  • TCP 192.168.0.1:20000 0.0.0.0:0 LISTENING

  • TCP 192.168.0.2:20000 0.0.0.0:0 LISTENING

とI.P.アドレスが表示されている場合は、I.P.アドレスを特定してバインドしている状態です。この場合、

  • 外付けのパラメータでバインドするI.P.アドレスを指定できるようになっていてそのI.P.アドレスを指定してバインドしている

  • ホスト名称に紐づくI.P.アドレスを内部的に求めてバインドしている

のどちらかだと考えられます。もし、外付けのパラメータでバインドしているようであれば、対応は比較的容易そうです。
同一ポート番号で異なるソケットをバインドするには、

  • 複数のI.P.アドレスを持つ

  • それぞれのソケットでそれぞれ明示的に異なるI.P.アドレスを指定してバインドする

必要があります。
今回はPC1とPC2のソフトウェアのみの変更が許されているようですから、以下の様な対応が必要になります。

  • PC1とPC2で動作していたソフトウェアを動作させるPCに2つのI.P.アドレス「192.168.0.1」「192.168.0.2」を持たせる。

  • PC1で動作していたソフトウェアは、「192.168.0.1」を明示的に指定してバインドするようにソフトウェアを修正する。

  • PC2で動作していたソフトウェアは、「192.168.0.2」を明示的に指定してバインドするようにソフトウェアを修正する。

明示的に指定してバインドする方法はソフトウェアの実装によりますが、先ほどの示したように、外付けのパラメータで指定されたI.P.アドレスを使用していてバインドしているようであれば、パラメータのみの修正で良いですね。
パラメータを使用してバインドしていないようであれば、ソフトウェアの修正が必要になります。
C言語で記述されているのであればbind()関数のロジック、JavaですとServerSocketオブジェクトを生成しているロジックあたりを確認してみてください。

編集 履歴 (0)
  • 上記のbind時にIPアドレスを指定する方法を実施した所、
    無事通信することを確認できました。
    非常に助かりました。ありがとうございました。
    -

何らかの手段でPC1サーバとPC2サーバを区別する必要があります。

例えば、HTTPサーバはHostヘッダーによって複数のバーチャルホストが立てられるようになっています。

編集 履歴 (0)
  • bind時にIPアドレスを指定して区別するようにしました。
    貴重な意見ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。