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 после обмена данными:
Георг ответ
server$ echo hello | nc -l -N 2000 client$ nc -d localhost 2000
После отправки
hello
, сервер встречаетEOF
на стандартном отправляетFIN
потому что-N
,Клиент получает сообщение и, в связи с
-d
видитEOF
на стандартный и отправляетFIN
, потому что сервер уже отправленFIN
,Соединение закрыто, и клиент, и сервер выходят.
Клиент инициирует закрытие
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 -