ТЛ; др
Смотрите выводы в самом конце.
преамбула
Я могу объяснить ваши результаты. Я использую Kubuntu, а не Debian, но все же я считаю, что основные моменты являются общими. Чтобы полностью понять, что происходит, полезно проанализировать случай TCP, а затем сравнить с UDP.
Если вы хотите повторить мое исследование, не прекращайте и не убивайте nc
если я не скажу так, или это не прекратится само по себе. Убей nc
s когда я скажу. Это очень важно. Прочитав полный ответ, вы поймете смысл этого.
Этот анализ требует нескольких терминалов (или tmux
, или screen
).
TCP чехол
Сначала избавьтесь от всех предыдущих процессов nc
.
killall nc
Запустите процесс прослушивания:
nc -l 6900
Изучите вывод lsof -i :6900
. Ваш nc
указан как процесс прослушивания.
Запустите процесс подключения:
nc localhost 6900
Изучите вывод lsof -i :6900
. Два nc
s являются концами установленного соединения.
Поскольку ваш первый nc
больше не слушает, вы можете запустить второй процесс прослушивания:
nc -l 6900
и второй процесс подключения:
nc localhost 6900
Напечатайте что-нибудь в каждой консоли, где работает nc
(не забывайте нажимать Enter каждый раз). Вы заметите, что есть два отдельных соединения. Вы можете установить третий, если хотите.
Снова проверьте lsof -i :6900
. Хотя два (ранее) прослушивающих nc
используют один и тот же порт 6900
, два соединения не смешиваются, потому что nc
на других концах используют разные порты. Когда пакет поступает на порт 6900
, ядро проверяет этот другой порт и решает, какой из (ранее) прослушивающих nc
должен его получить.
Вы можете запустить дополнительные (непарные) подключения nc
:
nc localhost 6900 || echo fail
и это немедленно провалится.
У вас все еще есть два отдельных соединения. Завершите один nc
каждой пары с помощью Ctrl + C или Ctrl + D, и вы заметите, что соответствующие концы также прекратятся. Это потому, что TCP ориентирован на соединение. Когда соединение изящно завершается с любого из его концов, другой конец уведомляется, чтобы он мог соответственно реагировать - в этом случае nc
просто завершается.
Случай UDP
Важный:
killall nc
Выполните следующие команды последовательно, каждая в отдельной консоли. Также проверьте lsof -i :6900
после каждого, чтобы увидеть, что происходит. Команды:
nc -ul 6900
nc -u localhost 6900
Введите что-то в первый ("прослушивание") nc
(нажмите Enter); проверьте lsof -i :6900
; введите что-нибудь во второй nc
(нажмите Enter); снова проверьте lsof -i :6900
и обратите внимание на изменение.
Затем подготовьте другую пару (в отдельных консолях):
nc -ul 6900
nc -u localhost 6900
Передайте несколько строк назад и вперед, чтобы увидеть, работает ли это. Завершите работу одного nc
с помощью Ctrl + C (Ctrl + D не будет работать) и обратите внимание, что другой nc
(на соответствующем конце) все еще работает. Другая сторона "соединения" не знает, когда "соединение" "прервано". Как вы могли видеть с lsof
он не знает, что "соединение" "установлено", пока данные не начнут течь.
Я приведу здесь несколько слов, потому что UDP не имеет соединения, и в этом главное отличие.
Что может быть сложным?
Пока все должно было работать. Пришло время начать объяснять свои предыдущие результаты, когда что-то не работает.
Важный:
killall nc
Подготовьте "слушающий" nc
:
nc -ul 6900
Проверьте lsof -i :6900
. Вывод будет выглядеть так:
… UDP *:6900
Подготовьте "соединительный" nc
:
nc -u localhost 6900
Проверьте lsof -i :6900
. Пример вывода (ваш 54766
может отличаться):
… UDP *:6900
… UDP localhost:54766->localhost:6900
Передайте некоторые данные из второго nc
в первый. Проверьте lsof -i :6900
:
… UDP localhost:6900->localhost:54766
… UDP localhost:54766->localhost:6900
Завершите второй nc
с Ctrl + C. Опять lsof -i :6900
… UDP localhost:6900->localhost:54766
Это означает, что первый nc
"общается" только с портом 54766
на другом конце "соединения". Когда вы пытаетесь подключиться с третьим nc
:
nc -u localhost 6900
Скорее всего, он выберет другой случайный порт на своей стороне. Попытайся. Вы сможете "пропустить" (примерно) две строки, так же, как вы делали это в своем вопросе, до того, как этот nc
завершится.
(Примечание: этот nc
завершается из-за ICMP-пакета, посмотрите это ; вы можете захватить пакет с помощью wireshark
как я.)
Однако вы можете принудительно настроить правильный порт (измените 54766
чтобы он соответствовал вашему lsof
):
nc -up 54766 localhost 6900
и этот четвертый nc
сможет передавать данные! Первый nc
не увидит разницы. Это будет, как если бы второй nc
никогда не завершался.
Завершите четвертый nc
прежде чем продолжить. Оставьте первый работающим.
Опция -v
Последняя загадка: почему nc -v -u localhost 6900
немедленно завершил работу ?
В приведенном выше примере у нас было четыре nc
s:
- первый - "слушающий";
- вторая - успешно подключена, затем прекращена;
- третий - невозможно подключиться из-за неправильного локального порта;
- четвертый - возможность подключения благодаря правильному (принудительному) локальному порту.
В моем Kubuntu nc -uv …
, если он второй , передает несколько символов X
, вероятно, для проверки соединения. По этой причине, если он третий , ему не нужно (около) двух строк внешнего ввода для сбоя, он сразу выходит из строя. После запуска первого nc
попробуйте:
nc -uv localhost 6900
Это должно потерпеть неудачу. Опять же, вы можете принудительно настроить правильный порт, и он будет работать так же, как четвертый nc
в приведенном выше примере.
nc -uvp 54766 localhost 6900
Когда я вызываю это, я вижу X
ы, напечатанные в консоли первого nc
.
очищающий
killall nc
Выводы
Мне кажется, у вас был ("слушающий") nc
который уже был связан с определенным портом на другой стороне "соединения", скорее всего из-за другого nc
(или чего-то еще), который успешно передал хотя бы один пакет , Другие ваши nc
пытались использовать другие порты на своей стороне и не могли связаться с этим первым.
Если я заменю localhost
на 127.0.0.1
, то прогресс будет
Ненужные. Полагаю, в этом случае вы только начали чистить, как мы сделали после killall nc
.