Здравствуйте! Есть у меня мега и ethernet shield к ней. Проблема в том, что мне необходимо сохранять приходящий http запрос полностью. Но, когда я увеличиваю размер буфера char[HTTP_req] контроллер начинает либо перезагружается на этапе записи байтов в буфер, либо просто виснет и ни на что не реагирует. Код прилагаю ниже: Код (C++): #include <SPI.h> #include <Ethernet.h> #include <SD.h> #define REQ_BUF_SZ 126 //Экспериментально подобраный, максимально возможный размер буфера, при котором все работает. Если вписать, допустим, 200, то картина будет совсем другой. File webFile; char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string char req_index = 0; // index into HTTP_req buffer byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; IPAddress ip(192, 168, 0, 177); EthernetServer server(80); void setup() { Ethernet.begin(mac, ip); server.begin(); (!SD.begin(4)); Serial.begin(9600); } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("New client"); // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); Serial.print(c); if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // save HTTP request character req_index++; } if (c == '\n' && currentLineIsBlank) { Serial.println("Request saved..."); Serial.print("strlen(HTTP_req)= "); Serial.println(strlen(HTTP_req)); Serial.println("Seeking hash..."); if (StrContains(HTTP_req, "Authorization: Basic bG9naW46cGFzc3dvcmQ=")) { Serial.println("Client authorized"); if (StrContains(HTTP_req, "GET / ")) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connnection: close"); client.println(); Serial.println("opening SD..."); webFile = SD.open("index.htm"); if (webFile) { Serial.println("Index.htm opened"); } } else if (StrContains(HTTP_req, "GET /UI.css")) { webFile = SD.open("UI.css"); if (webFile) { Serial.println("CSS file opened"); //client.println("Content-type: text/css"); //client.println("Connection: close"); client.println(); } } else if (StrContains(HTTP_req, "GET /script.js")) { webFile = SD.open("script.js"); if (webFile) { Serial.println("js file opened"); client.println("HTTP/1.1 200 OK"); client.println("Content-type: application/javascript"); client.println("Connection: close"); client.println(); } } else if (StrContains(HTTP_req, "GET /favicon.ico")) { client.println("HTTP/1.1 404 Not Found"); client.println(); } if (webFile) { while (webFile.available()) { client.write(webFile.read()); // send web page to client } webFile.close(); } } else { client.println(F("HTTP/1.1 401 Unauthorized")); client.println(F("WWW-Authenticate: Basic realm=\"Web Control Panel\"")); Serial.println("Client not authorized"); } Serial.println("Clear HTTP_req"); Serial.println(); req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); 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(1); // close the connection: client.stop(); } } void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } } char StrContains(char *str, const char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); Serial.println("StrContains invoked"); if (strlen(sfind) > len) { Serial.println("strlen(sfind)> len"); return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; }
Приведу вывод COM порта при размере буфера в 500 байт: Код (C++): New client GET / HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upg Причем, сколько контроллер не перезагружай, всегда чтение запроса остановится именно на этом месте. А вот, при размере буфера 126: Код (C++): New client GET / HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: ru X-Compress: null Request saved... strlen(HTTP_req)= 125 Seeking hash... StrContains invoked Client not authorized Clear HTTP_req New client GET / HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Authorization: Basic bG9naW46cGFzc3dvcmQ= Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Accept-Encoding: gzip, deflate, sdch Accept-Language: ru X-Compress: null Request saved... strlen(HTTP_req)= 125 Seeking hash... StrContains invoked Client authorized StrContains invoked opening SD... Index.htm opened Clear HTTP_req New client GET /UI.css HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Authorization: Basic bG9naW46cGFzc3dvcmQ= Accept: text/css,*/*;q=0.1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Referer: http://192.168.0.177/ Accept-Encoding: gzip, deflate, sdch Accept-Language: ru X-Compress: null Request saved... strlen(HTTP_req)= 125 Seeking hash... StrContains invoked Client authorized StrContains invoked StrContains invoked CSS file opened Clear HTTP_req New client GET /script.js HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Authorization: Basic bG9naW46cGFzc3dvcmQ= Accept: */* User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Referer: http://192.168.0.177/ Accept-Encoding: gzip, deflate, sdch Accept-Language: ru X-Compress: null Request saved... strlen(HTTP_req)= 125 Seeking hash... StrContains invoked Client authorized StrContains invoked StrContains invoked StrContains invoked js file opened Clear HTTP_req New client GET /favicon.ico HTTP/1.1 Host: 192.168.0.177 Connection: keep-alive Authorization: Basic bG9naW46cGFzc3dvcmQ= User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Accept: */* Referer: http://192.168.0.177/ Accept-Encoding: gzip, deflate, sdch Accept-Language: ru X-Compress: null Request saved... strlen(HTTP_req)= 125 Seeking hash... StrContains invoked Client authorized StrContains invoked StrContains invoked StrContains invoked StrContains invoked Clear HTTP_req
Кстати, при компилировании с размером буфера 500, компилятор выдает предупреждение: Not_Working_Global.ino:97:40: warning: overflow in implicit constant conversion [-Woverflow] Я не очень понимаю синтаксис этого, поэтому привожу ниже содержимое 94 и 40 строк: В 40 строке вывод в ком порт и ничего больше. а вот в 97 уже интересней: Код (C++): StrClear(HTTP_req, REQ_BUF_SZ); void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } }
Все, понял. Значит, нужно заменить тип данных в буфере. Кстати, на что? Что еще может хранить символы? Похоже, придется создать еще один массив. Да хотя блин. Ну вот объясните мне, что может помешать контроллеру выделить в памяти участок под 500 переменных типа char? Я ведь не в саму переменную пишу значение, которое выходит за рамки ее битности. Был бы рад учлышать чьи-нибудь комментарии по этому поводу
Попытка изменить тип данных внутри массива на беззнаковый (unsigned char) потерпела фиаско. Похоже, придется создавать еще 2 аналогичных буфера, следить за тем, чтобы в буферах оставались только полные строки, без "обрезаний", и уже в этих буферах искать необходимый мне хеш
Короче, сделаю так.. При чтении байтов с шилда я буду сохранять в буфер строку, смотреть, есть ли в ней полезная мне информация, и , если есть, сохранять. Если нет, то удалять. Таким образом проблема с размером буфера отпадает.
У функции 'StrClear' второй параметр 'length' имеет тип 'char', который не пригоден для хранения числа 500. Вот компилятор и ругается. Менять надо не тип данных буфера, а тип параметра 'length' в функци, например, на 'int'. При компиляции с большим буфером, что в конце выдает компилятор?
Для того что бы уменьшить кол-во занимаемой ОЗУ замените все строки типа Serial.println("Request saved..."); а так же client.println("Content-Type: text/html"); на Serial.println(F("Request saved...")); и соответственно client.println(F("Content-Type: text/html"));
Вот, обычный размер буфера: Код (C++): Sketch uses 23 728 bytes (9%) of program storage space. Maximum is 253 952 bytes. Global variables use 1 673 bytes (20%) of dynamic memory, leaving 6 519 bytes for local variables. Maximum is 8 192 bytes. Вот увеличенный Код (C++): Sketch uses 23 724 bytes (9%) of program storage space. Maximum is 253 952 bytes. Global variables use 2 047 bytes (24%) of dynamic memory, leaving 6 145 bytes for local variables. Maximum is 8 192 bytes. Не понимаю, в чем проблема-то... Ну не может мне не хватать памяти.
А есть у кого мега с ethernet shieldом? Просто, чтобы проверить симптомы. Может у меня с железом что-то не то