Запись файла с SD - карты на ethernet-клиент прекращает отправку примерно через 2980 символов, плата STM32f7
Я пытаюсь записать файл, найденный на SD-карте, в подключенный клиент Ethernet. Файл открывается нормально, и у нас нет проблем с написанием клиенту. В целях тестирования я также записываю строки, считанные из файла в последовательный порт, одновременно с записью на клиент. Однако происходит то, что все содержимое файла отображается в последовательном мониторе, но браузер получает только около 2978 символов. фактический файл, не включая заголовок, отправленный отдельно, составляет 4426 байт. Я провел тест, отправив около 260000 через 8000 "client.print (...)", и это сработало отлично.
Я приложил код. Все, что не является необходимым для основной функции кода, было удалено, чтобы дать нам минимум, необходимый для отладки. Я использую библиотеки EthernetWebServer_SSL_STM32 и SdFat. Мой код взят из примера веб - сервера.
/****************************************************************************************************************************
WebServer.ino - Simple Arduino web server sample for ESP8266 AT-command shield
For STM32F/L/H/G/WB/MP1 with built-in Ethernet LAN8742A (Nucleo-144, DISCOVERY, etc) or W5x00/ENC28J60 shield/module
EthernetWebServer_SSL_STM32 is a library for STM32 using the Ethernet shields to run WebServer and Client with/without SSL
Use SSLClient Library code from https://github.com/OPEnSLab-OSU/SSLClient
Built by Khoi Hoang https://github.com/khoih-prog/EthernetWebServer_SSL_STM32
Licensed under MIT license
*****************************************************************************************************************************/
#define REPLY_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n"
void Process_Client_Request()
{
FsFile file;
char line[500];
char Received_Character = '\0';
uint32_t Character_Index = 0;
uint32_t n;
uint32_t File_Length_Bytes;
uint32_t File_Length_Lines;
// listen for incoming clients
EthernetClient client = server.available();
// static ArduinoOutStream sout(client);
static ArduinoOutStream cout(Serial);
if (client)
{
// an http request ends with a blank line
bool currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank)
{
Serial.println(F("Sending response:\n"));
// send a standard http response header
// use \r\n instead of many println statements to speedup data send
client.print(REPLY_HEADER);
Serial.println(F(REPLY_HEADER));
// Open the SD card
if (!sd.begin(SD_CONFIG))
{
sd.initErrorHalt(&Serial);
}
// Specify the file to read
char fileName[] = "404.htm";
// Open the file to READ from the SD card
if (!file.open(fileName, O_READ))
{
sd.errorHalt(&Serial, F("open failed"));
}
File_Length_Bytes = file.fileSize();
File_Length_Lines = 0;
Serial.print(__DATE__); Serial.print(", "); Serial.println(__TIME__);
while ((n = file.fgets(line, sizeof(line))) > 0)
{
// Write the line to the client
client.print(line);
// Print the line
Serial.print(line);
File_Length_Lines++;
}
file.close();
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(10);
// close the connection:
client.stop();
Serial.println(F("\n\nClient disconnected"));
Serial.println("\n");
Serial.print("Total bytes read: "); Serial.println(File_Length_Bytes);
Serial.print("Total lines read: "); Serial.println(File_Length_Lines);
Serial.println("");
}
}
Есть какие-нибудь идеи, что я делаю не так?
Я попытался удалить все ссылки на SD-карту и жестко закодировал фразу для отправки через цикл while () - это сработало отлично. Пожалуйста, смотрите код ниже:
#define REPLY_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n"
void Process_Client_Request()
{
uint32_t File_Length_Bytes;
uint32_t File_Length_Lines;
uint16_t c;
uint32_t LineCount = 0;
// listen for incoming clients
EthernetClient client = server.available();
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial);
if (client)
{
// an http request ends with a blank line
bool currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank)
{
Serial.println(F("Sending response:\n"));
// send a standard http response header
// use \r\n instead of many println statements to speedup data send
client.print(REPLY_HEADER);
Serial.println(F(REPLY_HEADER));
client.print("</body></html>");
Serial.println("</body></html>");
while (LineCount < 8000)
{
client.print("This is line number: "); client.print(++LineCount); client.print("<br>\r\n");
Serial.print("This is line number: "); Serial.print(LineCount); Serial.print("<br>\r\n");
}
client.print("</html></body>");
Serial.println("</html></body>");
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(10);
// close the connection:
client.stop();
Serial.println(F("\n\nClient disconnected"));
Serial.println("\n");
}
}
При чтении строки текста с SD - карты и печати ее клиенту передача клиенту завершается примерно через 1279 символов плюс-минус. Когда это происходит, веб-браузер продолжает ждать получения дополнительных данных.
0
- Простая веб-страница с Ethernet-шилдом Arduino на SD-карте
- Получить изображение с SD-карты Arduino Ethernet Shield
- Конфликт 2 устройств SPI
- Как отправить информацию с сайта на ардуино?
- Как получить HTTPS на Arduino?
- Как увеличить скорость записи на SD-карту в Ардуино
- SD-карта не инициализируется
- Что означают эти контакты? Куда мне их подключить?
может быть, "файл".fgets(line, sizeof(line), "\n"))
или
client.write(line, countOfBytesReadWithfget);`?, @Jurajвы не используете библиотеку EthernetWebServer_SSL_STM32 в рассматриваемом фрагменте кода. это основное использование EthernetServer, как в примере веб-сервера библиотеки Ethernet., @Juraj
Спасибо вам за ваши предложения, Юрай. Я действительно реализовал и то, и другое, но без каких-либо изменений. Я все еще не получаю весь файл целиком., @JackOfAllTrades99
Я думаю, что \n не считается, поэтому чтение заканчивается на пустой строке, @Juraj
Вывод на клиент обычно заканчивается в середине строки. Оказывается, что client.print() перестает отправлять данные после заданного количества символов., @JackOfAllTrades99
Может быть, это связано с размером буфера? https://github.com/OPEnSLab-OSU/SSLClient#implementation-gotchas, @tim
какое оборудование и библиотеку Ethernet вы используете? Вы используете библиотеку SSLclient?, @Juraj
Это стартовое сообщение при запуске кода: Запустите веб-сервер на NUCLEO_F767ZI, используя библиотеку LAN8742A Ethernet и STM32Ethernet EthernetWebServer_SSL_STM32 v1.3.0 Я определил, что код использует файл ethernet.h, найденный здесь: Arduino/libraries/STM32duino_LwIP/src/netif/ethernet.h. Этот файл не имеет возможности увеличить размер буфера, как предлагал Тим. Попробовал просмотреть различные заголовочные файлы, на которые ссылаются ссылки, но так и не смог найти настройку буферизации отправки., @JackOfAllTrades99
Самое смешное, что это только проблема при чтении строки с SD-карты и записи ее клиенту. Если я исключу SD-карту из уравнения и запишу консервированные данные, это работает нормально. Это, кажется, указывает на то, что это не может быть проблемой буфера отправки. У меня кончаются идеи., @JackOfAllTrades99
Просто интересно, не проблема ли это со временем. Версия SD-карты отправляет 500 байт на "печать", в то время как жестко закодированная версия отправляет около 30 байт на "печать". В качестве эксперимента попробуйте замедлить внутренний цикл "while" с помощью таймера "millis ()" (возможно, 100 мс на "печать") и увеличить конечную задержку(10) до "delay(1000)" после внешнего цикла "while". Или, может быть, SD-библиотека мешает работе библиотеки Ethernet?, @tim
попробуйте
client.write(line, n);
вместоclient.print(line);
(кстати: это не строка), @JurajЗадержки были хорошей идеей, но, к сожалению, не возымели никакого эффекта. Я уже пробовал использовать client.write, а также потоковую передачу на клиент. Результаты были согласованы для всех этих методов., @JackOfAllTrades99
Я взял жестко закодированный вывод и создал файл на SD-карте с 8000 строк содержимого, т. е.,
<html><body> Это номер строки: 1<br> Это номер строки: 2<br> Это номер строки: 3<br> ...
но самое странное, что здесь происходит, - это то, что распечатка останавливается на 201 строке для печати на последовательный порт и 104 строках для клиента., @JackOfAllTrades99Это может быть хитроумная SD-карта. Библиотека, которую вы используете, возвращает/устанавливает коды ошибок для
файла.fgets(line, sizeof(line))
? Сравните с [fegts
](https://www.cplusplus.com/reference/cstdio/fgets/) и [ferror
](https://www.cplusplus.com/reference/cstdio/ferror/). Не могли бы вы предоставить ссылку на библиотеки, которые вы используете?, @timэто ссылка на библиотеку, которую я использую для функций SD-карты: https://github.com/greiman/SdFat ... Утром я снова займусь этим. Спасибо вам за всю вашу помощь до сих пор!, @JackOfAllTrades99
Что касается SD - карты, то я пробовал переключаться между двумя различными марками и размерами SD-карт с разными форматами-результат был одинаковым между ними. Как правило, я использую только карты SanDisk Ultra, так как они доказали свою надежность на протяжении многих лет. Fgets() генерирует общий (-1) код ошибки. Я проверил это, и оно не было выброшено. Я также протестировал использование нескольких различных файлов на SD-карте, чтобы исключить возможность внедрения мошеннических кодов в текст. И снова никаких изменений., @JackOfAllTrades99
Странно то, что когда я комментирую
client.print
и записываю только в серийный номер, нам удается распечатать все строки файлов в серийный номер. Наш вывод преждевременно завершается только в том случае, если мы пишем клиенту. Это похоже на своего рода конфликт между библиотекой Ethernet и библиотекой SdFat., @JackOfAllTrades99Я попытался использовать стандартную библиотеку Arduino SD вместо библиотеки SdFat. Я также сделал
client.write(myFile.read());
вместо чтения в переменную 'line', в остальном код не изменился. Те же результаты - вывод клиенту прекращается примерно после 104 из 8000 переданных строк., @JackOfAllTrades99Разделите вашу программу на функциональные блоки. Протестируйте каждый блок отдельно. Если все они работают отдельно, добавляйте блок за блоком (2 блока, 3 блока и т. Д.) и тестируйте после каждого добавленного блока. Таким образом, вы можете точно определить, где возникает проблема, и иметь лучшее изменение для ее решения., @PimV
Комментарии не предназначены для расширенного обсуждения; этот разговор был [перенесен на chat](https://chat.stackexchange.com/rooms/128516/discussion-on-question-by-jackofalltrades99-writing-file-from-sd-card-to-etherne)., @Juraj