Назад | Перейти на главную страницу

BSD nc (netcat) не завершается при EOF

Хост А:

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

Хост B:

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-РЕЛИЗ-p4, Только IPv4.

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

серверы NC (nc -l) и клиенты выходят только после того, как взаимное соединение было закрыто. То есть, если каждая из сторон отправила ПЛАВНИК пакет другой стороне.

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

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

  • после EOF на stdin при запуске с аргументом -N
  • после EOF на stdin, когда сервер уже отправил пакет 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 на хосте A по-прежнему необходимо закрыть TCP подключение по EOF.


В итоге

Хост А:

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

Хост B:

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