Bash HTTP сервер для получения изображений curl 55 ошибка “разбитая труба”

Вопрос или проблема

Я новичок в написании bash-скриптов и в данный момент в основном использую chatgpt для создания шаблонов. Я пытаюсь создать простой HTTP-сервер на базе netcat, который будет принимать и хранить .png файлы. У меня есть второй скрипт, предназначенный для тестирования этого, и сейчас он выдает ошибку broken pipe. Я не совсем понимаю, что это значит в этом контексте, так как на самом деле я не передаю данные по сети. Буду признателен за любые подсказки. Я не нов в программировании, но нов в bash/сетях/web-разработке.

Вывод терминала тестового скрипта:

Отправка PUT-запроса на http://127.0.0.1:1881...
*   Пробую 127.0.0.1:1881...
  % Всего    % Получено % Отправлено  Средняя скорость   Время    Время     Время  Текущая
                                 Загрузка  Загрузка   Всего   Израсходовано   Осталось  Скорость
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Подключено к 127.0.0.1 (127.0.0.1) порт 1881 (#0)

PUT /test_image.png HTTP/1.1

Host: 127.0.0.1:1881

User-Agent: curl/7.81.0

Accept: */*

Content-Length: 16074

Expect: 100-continue

* Отметить пакет как несовместимый с многоразовым использованием

HTTP/1.1 100-continue 
* Ошибка отправки: Broken pipe
  0 16074    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Закрытие соединения 0

curl: (55) Ошибка отправки: Broken pipe

Тестовый скрипт:

#!/bin/bash

# Определите адрес сервера и порт
SERVER_ADDRESS="127.0.0.1"
SERVER_PORT=1881

# Файл для отправки
TEST_FILE="test_image.png"

# Проверьте, существует ли тестовый файл
if [[ ! -f "$TEST_FILE" ]]; then
  echo "Тестовый файл '$TEST_FILE' не существует. Создание временного файла..."
  echo "Это тестовый файл." > "$TEST_FILE"
fi

# Используйте curl для отправки PUT-запроса с опцией --upload-file
echo "Отправка PUT-запроса на http://$SERVER_ADDRESS:$SERVER_PORT..."
RESPONSE=$(curl -v http://$SERVER_ADDRESS:$SERVER_PORT --upload-file $TEST_FILE)
# Проверьте код HTTP-ответа
if [[ "$RESPONSE" == "200" ]]; then
  echo "PUT-запрос выполнен успешно. Сервер вернул HTTP 200 OK."
else
  echo "PUT-запрос не удался. Сервер вернул HTTP $RESPONSE."
fi

Скрипт сервера:

#!/bin/bash

# Определите IP-адрес и порт для HTTP-сервера
IP_ADDRESS="127.0.0.1"
PORT=1881

# Каталог для хранения полученных данных
UPLOAD_DIR="Data"

# Запустите HTTP-сервер с помощью netcat
echo "Запуск HTTP-сервера на $IP_ADDRESS:$PORT..."
while :
do
  echo -e "HTTP/1.1 100-continue \r\n" | nc -l -s $IP_ADDRESS -p $PORT -q 1 > request.txt

    # Сгенерируйте имя файла на основе временной метки
    TIMESTAMP=$(date +"%Y%m%d%H%M%S")
    OUTPUT_FILE_PATH="$UPLOAD_DIR/received_$TIMESTAMP.png"

    # Сохраните полученные данные в определенный путь вывода
    sed -n '/\r\n\r\n/{n;p;}' request.txt > "$OUTPUT_FILE_PATH"
    echo "Полученные данные PUT сохранены в $OUTPUT_FILE_PATH"

done

Ответ или решение

Ошибка "Broken pipe" (система прервала соединение) при работе с curl и netcat может возникать по нескольким причинам. Ниже я представлю детальный анализ указанных вами скриптов и предложу, как решить эту проблему.

1. Понимание проблемы "Broken pipe"

Ошибка "Broken pipe" указывает на то, что одно из соединений прервало связь, пока другое соединение всё ещё пыталось передать данные. В вашем случае, это означает, что эталонный скрипт, отправляющий данные с помощью curl, пытается отправить данные на сервер через netcat, который, возможно, закрыл соединение до того, как все данные были отправлены.

2. Анализ скриптов

Скрипт клиента

#!/bin/bash

# Определяем адрес сервера и порт
SERVER_ADDRESS="127.0.0.1"
SERVER_PORT=1881

# Файл для отправки
TEST_FILE="test_image.png"

# Проверяем, существует ли тестовый файл
if [[ ! -f "$TEST_FILE" ]]; then
  echo "Тестовый файл '$TEST_FILE' не существует. Создаем его..."
  echo "This is a test file." > "$TEST_FILE"
fi

# Используем curl для отправки PUT запроса
echo "Отправка PUT запроса на http://$SERVER_ADDRESS:$SERVER_PORT..."
RESPONSE=$(curl -v --upload-file "$TEST_FILE" http://$SERVER_ADDRESS:$SERVER_PORT)
# Проверяем HTTP код ответа
if [[ "$RESPONSE" == *"200 OK"* ]]; then
  echo "PUT запрос успешно выполнен. Сервер вернул HTTP 200 OK."
else
  echo "PUT запрос завершился неудачно. Сервер вернул HTTP $RESPONSE."
fi

Скрипт сервера

#!/bin/bash

# Определяем IP адрес и порт для HTTP сервера
IP_ADDRESS="127.0.0.1"
PORT=1881

# Директория для хранения полученных данных
UPLOAD_DIR="Data"

# Запускаем HTTP сервер с помощью netcat
echo "Запуск HTTP сервера на $IP_ADDRESS:$PORT..."
mkdir -p "$UPLOAD_DIR"
while :; do
  echo -e "HTTP/1.1 100-continue\r\n" | nc -l -s $IP_ADDRESS -p $PORT -q 1 > request.txt

  # Генерируем имя файла на основе текущей метки времени
  TIMESTAMP=$(date +"%Y%m%d%H%M%S")
  OUTPUT_FILE_PATH="$UPLOAD_DIR/received_$TIMESTAMP.png"

  # Сохраняем полученные данные в файл
  sed -n '/\r\n\r\n/{n;p;}' request.txt > "$OUTPUT_FILE_PATH"
  echo "Полученные данные сохранены в $OUTPUT_FILE_PATH"
done

3. Возможные источники проблемы

  • Проблема с ответом от сервера: Когда клиентское приложение обращается к серверу с запросом PUT, сервер должен быть готов принять данные. В вашем случае сервер отправляет ответ "HTTP/1.1 100-continue" и сразу же прекращает ожидать. Это может вызвать ошибки на стороне клиента, так как клиент может интерпретировать это как закрытие соединения до начала передачи данных.

  • Генерация имен файлов: Директория для сохранения файлов может не существовать, в результате чего в попытке сохранить файл возникнет ошибка.

4. Решения

Изменение сервера

  1. Убедитесь, что директория для хранения файлов существует:

    mkdir -p "$UPLOAD_DIR"
  2. После отправки 100-continue сервер должен быть готов получить данные. Измените логику вашего сервера на следующее:

while :; do
  # Чтение запроса с помощью nc
  { echo -e "HTTP/1.1 200 OK\r\n"; cat; } | nc -l -s $IP_ADDRESS -p $PORT -q 1 > request.txt

  # Генерируем имя файла на основе текущей метки времени
  TIMESTAMP=$(date +"%Y%m%d%H%M%S")
  OUTPUT_FILE_PATH="$UPLOAD_DIR/received_$TIMESTAMP.png"

  # Сохраняем полученные данные в файл
  sed -n '/\r\n\r\n/{n;p;}' request.txt > "$OUTPUT_FILE_PATH"
  echo "Полученные данные сохранены в $OUTPUT_FILE_PATH"
done
  1. Убедитесь, что всё настраивается правильно. Сервер должен корректно обрабатывать данные от клиента и подтверждать успешный прием файлов.

Заключение

Обратите внимание на то, как сервер обрабатывает запросы и статусные коды. Убедитесь, что вы корректно открываете, принимаете и закрываете соединения. После внесения указанных изменений тестовый сценарий с использованием curl должен пройти успешно без ошибок "Broken pipe".

Оцените материал
Добавить комментарий

Капча загружается...