UDPポート6666を介した通信を実験しています(netconsoleのリスナーを設定することを目標としていますが、ここではあまり関係ありません)。
リスニング側では、nc -luv 6666
。送信側では、nc -uv LISTENER_IP 6666
。私は送受信でき、人生は良いです。
リスナーを実行したままにしますが、送信者を強制終了して、別の送信者を開始します。すぐに終了します。ネットワークトレースにより、受信サーバーがICMP Port Unreachableを送信していることがわかります。ただし、リスナーは引き続き待機します。
$ Sudo ss -nlup|grep 6666
UNCONN 0 0 :::6666 :::* users:(("nc",pid=3417,fd=3))
私は受信機を殺して、新しいものを走らせます。私が送信者を殺すまで、すべては以前のように機能します。
送信側と受信側は同じネットワーク上の物理マシンです。物理マシンとその上で実行しているVMの間で同じテストを実行すると、同じ結果が得られます。
この動作はどのように説明できますか?
UDP「接続」が機能する方法により、これは予想される動作です。これについては nc6(1)
のマニュアルページ ( "UDP")で説明しますが、socat
およびnc
にも適用できます。
Netcat6のUDPサポートは、接続モードと待機モードの両方で非常にうまく機能します。リッスンモードでUDPを使用する場合、netcat6は、指定されたオプションのアドレスやポート(指定されている場合)に一致する任意のソースからのUDPパケットを受け入れます。ただし、最初のパケットが受信されると、netcat6は将来そのクライアントからのパケットのみを受信します。これは、UDPソケットを「接続済み」状態にすることによって行われます(udp(4)およびconnect(2)を参照)。他のソースからのパケットはカーネルによって破棄され、ICMP到達不能応答が送信されます。
UDPを使用してリモートホストに接続する場合、nc6は、リモートサーバーがリッスンしているかどうかに関係なく、接続が開いていることを報告します。これは、UDPがコネクションレス型プロトコルであるため、実際には接続の確立が必要ないためです。ただし、データの最初のパケットを送信した後、サーバーがICMP到達不能応答で応答し、nc6が「接続拒否」エラーメッセージで終了する場合があります。
送信側から接続すると、ランダムなUDPソースポートが選択されます。次に、レシーバーはその特定のHost:port
ペアにバインドし、それ以降は他の接続をリッスンしません。これを解決するには、送信者が常に同じポートを使用するように強制する必要があります。この例ではsocat
を使用しました。
リスナー:
# socat -d -d UDP-LISTEN:6666 stdout
2018/01/29 22:02:02 socat[20969] N listening on UDP AF=2 0.0.0.0:6666
2018/01/29 22:02:07 socat[20969] N accepting UDP connection from AF=2 10.100.0.5:39000
2018/01/29 22:02:07 socat[20969] N using stdout for reading and writing
2018/01/29 22:02:07 socat[20969] N starting data transfer loop with FDs [5,5] and [1,1]
hello
bye
hello1
bye1
送信者:
# socat -d -d stdin UDP:listener-Host:6666
2018/01/29 22:01:56 socat[8237] N using stdin for reading and writing
2018/01/29 22:01:56 socat[8237] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:01:56 socat[8237] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:01:56 socat[8237] N starting data transfer loop with FDs [0,0] and [5,5]
hello
bye
2018/01/29 22:02:10 socat[8237] N socket 1 (fd 0) is at EOF
2018/01/29 22:02:10 socat[8237] N exiting with status 0
# socat -d -d stdin UDP:listener-Host:6666
2018/01/29 22:02:13 socat[8238] N using stdin for reading and writing
2018/01/29 22:02:13 socat[8238] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:02:13 socat[8238] N successfully connected from local address AF=2 10.100.0.5:57125
2018/01/29 22:02:13 socat[8238] N starting data transfer loop with FDs [0,0] and [5,5]
hello
2018/01/29 22:02:16 socat[8238] E read(5, 0x5619f9b09330, 8192): Connection refused
2018/01/29 22:02:16 socat[8238] N exit(1)
# socat -d -d stdin UDP:listener-Host:6666,sourceport=39000
2018/01/29 22:05:17 socat[8280] N using stdin for reading and writing
2018/01/29 22:05:17 socat[8280] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:05:17 socat[8280] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:05:17 socat[8280] N starting data transfer loop with FDs [0,0] and [5,5]
hello1
bye1
2018/01/29 22:05:23 socat[8280] N socket 1 (fd 0) is at EOF
2018/01/29 22:05:24 socat[8280] N exiting with status 0
ご覧のように、送信元で送信元ポートが変更されましたが、同じポートを再利用するように強制すると、機能しました。