web-dev-qa-db-ja.com

BSD nc(netcat)がEOFで終了しない

ホストA:

_tar cf -  stuff | dd | nc  -N -l 12987
_

ホストB:

_nc a.example.com 12987 | dd | tar tf - 
_

ホストAでは、ddtarの完了後にその概要を出力します。したがって、tarがパイプ/ファイルを閉じることは明らかです-> EOF

165040 + 0レコード165040 + 0レコードアウト84500480バイトを25.464802秒で転送(3318325バイト/秒)

両方のホストでncは終了せずに喜んでそこに座っています。 nc(1)

_   -N      shutdown(2) the network socket after EOF on the input.  Some
           servers require this to finish their work.
_

したがって、ホストAではncEOFを確認し、いまいましいソケットを閉じ、ホストBではncでTCP接続終了を確認する必要があります。 stdoutstdin/dd/tar)を閉じているはずです。

ncstdout /ホストBで終了し、ホストAで終了するように指示するにはどうすればよいですか

ncバグ?

_-D_(デバッグ)は何もしません。 ncはバージョン番号さえもわかりません...sigh

どちらのホストもFreeBSD 10.3-RELEASE-p4、IPv4のみです。

6
georg

私もnetcatの振る舞いに戸惑い、コードを掘り下げました。これが全体の話です:

ncサーバー(nc -l)とクライアントは、相互接続が閉じられた後にのみ終了します。つまり、各パーティが [〜#〜] fin [〜#〜] パケットを他のパーティに送信した場合です。

サーバーは、クライアントからFINパケットを受信した後、常にFINパケットを送信します。 (サーバーがすでにFINパケットを送信していない限り)。

クライアントは次のいずれかでFINパケットを送信します。

  • stdinのEOFの後、引数-Nを指定して実行した場合
  • stdinのEOFの後、サーバーがすでにFINパケットを送信したとき

オプション-dは、標準入力で常にEOFを意味します。

オプション-Nは、stdinでFINを検出した後、常にEOFを送信することを意味します。

データ交換後にncプロセスを終了する方法:

  1. ジョージの答え

    server$ echo hello | nc -l -N 2000
    client$ nc -d localhost 2000
    

    helloを送信した後、サーバーは標準入力でEOFを検出し、-Nが原因でFINを送信します。

    サーバーはすでにEOFを送信しているため、クライアントはメッセージを受信し、-dにより、stdinでFINを確認してFINを送信します。

    接続が閉じられ、クライアントとサーバーの両方が終了します。

  2. クライアントがクローズを開始

    server$ echo hello | nc -l 2000
    client$ nc -dN localhost 2000
    

    サーバーはstdinのEOFの後も接続を開いたままにします。

    -Nが原因で、クライアントはstdinでEOFを確認してFINを送信します。

    サーバーは、クライアントのFINを受信した後、FINを送信します。

    接続が閉じられ、クライアントとサーバーの両方が終了します。

7
ens

nc双方向接続を確立します。つまりホストBからホストAにstdinを送信し、必要なものをAからBに送信します。

ホストBで-dを使用して、stdinを無視します。 EOFのTCP接続を閉じるには、ホストAの-Nが引き続き必要です。


要約すれば

ホストA:

tar cf -  stuff | dd | nc  -N -l 12987

ホストB:

nc -d a.example.com 12987 | dd | tar tf - 
4
georg