Я заметил странное поведение при работе с netcat и UDP. Я запускаю экземпляр (экземпляр 1) netcat, который прослушивает порт UDP:
nc -lu -p 10000
Поэтому я запускаю еще один экземпляр netcat (экземпляр 2) и пытаюсь отправить дейтаграммы моему процессу:
nc -u 127.0.0.1 10000
Я вижу дейтаграммы. Но если я закрываю экземпляр 2 и снова запускаю netcat (экземпляр 3):
nc -u 127.0.0.1 10000
Я не вижу дейтаграмм на терминале экземпляра 1. Очевидно, что операционная система назначает другой порт-источник UDP в экземпляре 3 относительно экземпляра 2, и проблема заключается в следующем: если я использую тот же порт источника экземпляра 2 (пример 50000):
nc -u -p 50000 127.0.0.1 10000
снова экземпляр 1 netcat получает дейтаграммы. UDP — это протокол без установления соединения, так почему? Это стандартное поведение netcat?
когда nc
прослушивает сокет UDP, он «блокирует» порт источника и IP-адрес первого полученного пакета. Проверьте этот след:
socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(10000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
recvfrom(3, "f\n", 2048, MSG_PEEK, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, [16]) = 2
connect(3, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
Здесь вы можете видеть, что он создал сокет UDP, настроил его для повторного использования адреса и привязал его к порту 10 000. Как только он получил свою первую дейтаграмму (из порта 52 832), он выпустил connect
системный вызов, «соединяющий» его с 127.0.0.1:52,832. Для UDP connect
отклоняет все пакеты, которые не соответствуют IP-адресу и порту в connect
,
Использовать -k
опция:
nc -l -u -k 0.0.0.0 10000
Отказавшись от netcat в моей версии ОС, она довольно короткая и выполняет свою работу:
#!/usr/bin/ruby
# Receive UDP packets bound for a port and output them
require 'socket'
require 'yaml'
unless ARGV.count == 2
puts "Usage: #{$0} listen_ip port_number"exit(1)
end
listen_ip = ARGV[0]
port = ARGV[1].to_i
u1 = UDPSocket.new
u1.bind(listen_ip, port)
while true
mesg, addr = u1.recvfrom(100000)
puts mesg
end
Как объясняет принятый ответ, ncat
кажется не поддерживать --keep-open
с протоколом UDP. Однако, сообщение об ошибке, которое это печатает, подсказывает обходной путь:
Ncat: UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec. QUITTING.
Просто добавив --exec /bin/cat
позволяет --keep-open
использоваться. И вход, и выход будут подключены к /bin/cat
с эффектом превращения его в «эхо-сервер», потому что все, что отправляет клиент, будет скопировано обратно на него.
Чтобы сделать что-то более полезное с вводом, мы можем использовать операторы перенаправления оболочки (таким образом, требуя --sh-exec
вместо --exec
). Чтобы увидеть данные на терминале, это работает:
ncat -k -l -u -p 12345 --sh-exec "cat > /proc/$$/fd/1"
Предостережение: приведенный выше пример отправляет данные на стандартный вывод ncat родительская оболочка, что может сбить с толку, если в сочетании с дополнительными перенаправлениями. Просто добавить весь вывод в файл проще:
ncat -k -l -u -p 12345 --sh-exec "cat >> ncat.out"