BSD nc (netcat) не заканчивается на EOF

Хост А:

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

Хост Б:

nc a.example.com 12987 | dd | tar tf - 

На хосте А dd печатает свое резюме после tar завершается. Таким образом, ясно, что 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 nc должен был увидеть EOF закрыл чертову розетку и на хосте B nc должен был видеть разрыв соединения TCP и должен был закрыться stdout (stdin из dd / tar).

Как мне сказать nc закрывать stdout / завершить на хосте B и завершить на хосте A.

nc ошибка?

-D (отладка) ничего не делает. nc не могу даже сказать его номер версии... вздох

Оба хоста являются только FreeBSD 10.3-RELEASE-p4, IPv4.

2 ответа

Решение

Я тоже был озадачен поведением netcat, поэтому копался в коде. Вот и вся история:

nc серверы (nc -l) и клиенты выходят только после того, как взаимное соединение было закрыто. То есть, если каждая из сторон отправила пакет FIN другой стороне.

Сервер всегда отправляет FIN пакет после получения FIN пакет от клиента. (Если сервер уже не отправил FIN пакет.)

Клиент отправляет пакет FIN либо:

  • после EOF на стандартный ввод, когда запускается с аргументом -N
  • после EOF на стандартный ввод, когда сервер уже отправил пакет FIN

вариант -d всегда подразумевает EOF на стандартном

вариант -N всегда подразумевает отправку FIN после встречи EOF на стандартном

Способы выхода из процессов nc после обмена данными:

  1. Георг ответ

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

    После отправки hello, сервер встречает EOF на стандартном отправляет FIN потому что -N,

    Клиент получает сообщение и, в связи с -dвидит EOF на стандартный и отправляет FIN, потому что сервер уже отправлен FIN,

    Соединение закрыто, и клиент, и сервер выходят.

  2. Клиент инициирует закрытие

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

    Сервер сохраняет соединение открытым после EOF на стандартном

    Клиент видит EOF на стандартный и отправляет FIN, потому что -N,

    Сервер отправляет FIN после получения клиента FIN,

    Соединение закрыто, и клиент, и сервер выходят.

nc устанавливает двунаправленное соединение. Т.е. отправляет stdin от хоста B к хосту A, а также желаемый от A до B.

использование -d на хосте B игнорировать stdin, -N на хосте А все еще необходимо закрыть TCP подключение по EOF.


В итоге

Хост А:

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

Хост Б:

nc -d a.example.com 12987 | dd | tar tf - 
Другие вопросы по тегам