На моем терминале Raspberry Pi 3 (Linux) я набрал следующее и нажал Enter:

printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/' | nc -l 2345

Raspberry Pi 3 является частью моей домашней сети с фиксированным адресом 192.168.0.8. Затем на своем Mac я набрал следующее в браузере (Chrome) и нажал Enter:

192.168.0.8:2345

Я вижу запрос браузера GET на моем терминале Linux (Raspberry Pi), но слушатель nc застревает и не отправляет ответ (сообщение перенаправления HTTP 302) в браузер.

Только когда я остановлю программу nc , нажав Ctrl+C , браузер получит ответное сообщение и отобразит веб-сайт https://www.eff.org .

Кто-нибудь знает, почему слушатель nc застревает вместо отправки ответа и закрывает соединение?

1 ответ1

0

Я повторил твою проблему. Когда я подключаюсь к другому nc вместо браузера, я вижу, что ответ отправляется немедленно. Я думаю, что ваш браузер также получает ответ, но поскольку nc не прерывает соединение, браузер не знает, что это все, и можно продолжить перенаправление.

(Примечание: во время моих тестов мне понадобился последний \r\n в ответе от nc чтобы успешно перенаправить мой браузер, поэтому все мои примеры используют это исправление.)


Редактировать: простое исправление

Здесь я нашел следующее:

HTTP-запросы и HTTP-ответы используют общий формат сообщения RFC 822 для передачи требуемых данных. Этот общий формат сообщения состоит из следующих четырех элементов.

  • [...]
  • [...]
  • Пустая строка (т. Е. Строка, не предшествующая CRLF), указывающая конец полей заголовка
  • [...]

Итак, ваш ответ должен быть:

printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n\r\n' | ...

После получения этого ваш браузер должен продолжить перенаправление, прервав соединение с nc от своего имени. В начале декабря 2017 года он работает с Оперой и Вивальди; он не работает с Firefox, Chrome или Safari, для которых вам может потребоваться другое исправление (см. ниже).



Оригинальный, теперь неполноценный ответ (он все еще может быть полезен для связи не по HTTP с nc)

В соответствии с этим ответом о сбое сервера вам нужно использовать -c , -q или аналогичный параметр, в зависимости от реализации nc

В моем Debian установлена версия с поддержкой -q . затем

printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -q 0 -l -p 2345

работает нормально (обратите внимание, мне также нужно -p чтобы указать порт). Объяснение:

-q seconds
после EOF на stdin , подождите указанное количество секунд и затем выйдите. Если секунды отрицательны, подождите вечно (по умолчанию).


Если у вашего nc нет правильной опции, то обходной путь может заключаться в обнаружении связи с клиентом и уничтожении всей командной строки. Пример, который работает в моем Debian, bash:

printf 'HTTP/1.1 302 Moved\r\nLocation: https://www.eff.org/\r\n' | nc -l -p 2345 | { read foo; sleep 1; kill 0; }

При запуске канала bash помещает каждый процесс в одну группу процессов; kill 0 отправляет сигналы всей группе процессов. Таким образом, nc уничтожается примерно через 1 секунду после получения любого запроса, запускающего read .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .