从 Arduino 代码中将 HTML 用作 C 数组 - 字符串大小限制问题

Serving HTML as C array from Arduino code - String size limit problem

我一直在 Wiznet W5100S-EVB-Pico 上开发 HTML / websocket 服务器,在 Arduino IDE 中编程。到目前为止一切正常,但我 运行 我认为是字符串大小限制。我想这是代码处理 const char 的方式,但我不知道如何正确处理。

希望有人愿意帮忙:)

让我解释一下:

const char c_index_html[] = {
0x3c,0x21,0x44,0x4f,0x43,..., ..., 0x6d,0x6c,0x3e};
#include "index_html.h"

现在实际服务于“HTML”的代码

if (web_client){
    
    Serial.println("New client");
    // an http request ends with a blank line
    bool currentLineIsBlank = true;

    while (web_client.connected()){
      
      if (web_client.available()){
        
        char c = web_client.read();
        
        if (c == '\n' && currentLineIsBlank)                // if you've gotten to the end of the line (received a newline
        {                                                   // character) and the line is blank, the http request has ended,
          Serial.println(F("Sending response"));            // so you can send a reply

          String strData;
          strData = c_index_html;
          web_client.println(strData);
          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;
        }
      }
    }

这不是最漂亮的代码,它是从示例中拼凑而成的,现在罪魁祸首似乎是:

String strData;
strData = c_index_html;
web_client.println(strData);

当我向 HTML 添加额外的代码并查看页面源代码时,代码不完整。我测试了将 HTML 减少到最小值并解决了问题。

所以我的主要问题是:

还有:

非常感谢您一路走来 post 如果您有任何建议,我将不胜感激 ;)

编辑: There is a bug in the ethernet library shown in this post.

不知道对你有没有影响;你应该看看你的库实现。


我假设 web_client 是 Arduino 库中 EthernetClient 的一个实例。

EthernetClient::println继承自Print via Stream,定义为write,即:

size_t EthernetClient::write(const uint8_t *buf, size_t size)
{
    if (_sockindex >= MAX_SOCK_NUM) return 0;
    // This library code is not correct:
    if (Ethernet.socketSend(_sockindex, buf, size)) return size;
    setWriteError();
    return 0;
}

所以我们看到它要求套接字将缓冲区发送到某个大小。 套接字可以响应大小或 0参见编辑);如果它以 0 响应,则有一个错误条件需要检查。

编辑: 它应该是这样工作的。由于 write 总是返回请求的大小而不告诉您写入了多少,因此您无法使用 print/write 工具解决问题,需要直接使用 socketSend.

您没有检查此写入的结果(应该通过 println),因此您不知道套接字是否发送了 size 字节、0 字节或一些之间的数字。

EthernetClient::connect 中我们看到它正在打开一个 TCP 流:

_sockindex = Ethernet.socketBegin(SnMR::TCP, 0);

当您调用 socketSend 时,您实际上只是将缓冲区复制到网络堆栈中的缓冲区中。 TCP 驱动程序会尽可能地写出该缓冲区。如果您写入该缓冲区的速度快于它被刷新到网络的速度,那么您将填满它并且您的 socketSend 调用将开始返回 < size 字节。参见 Does send() always send whole buffer?

所以您可能是对的,您的字符串太长了。你需要做的是分散你的写作。网络上有无数教程介绍了这一点;在你的例子中大致是这样的:

...

size_t bytesRemaining = 0;

while (web_client.connected()){

  if (bytesRemaining > 0) {
    // Still responding to the last request
    char const* const cursor = c_index_html 
                             + sizeof(c_index_html) 
                             - bytesRemaining;
    size_t const bytesWritten = web_client.write(cursor, bytesRemaining);

    if (!bytesWritten) {
      // check for error
    }
    bytesRemaining -= bytesWritten;

    if (bytesRemaining == 0) {
      // End the message. This might not write! 
      // We should add the '\n' to the source array so 
      // it's included in our write-until-finished routine.
      web_client.println();
      // Stop listening
      break;
    }

  } else if (web_client.available()){
    // Time for a new request
    
    char c = web_client.read();
    
    if (c == '\n' && currentLineIsBlank)               
    {                                                   
      Serial.println(F("Sending response"));            
      // Start responding to this request
      bytesRemaining = sizeof(c_index_html);
      continue;
    }

    ...

这就是我的想法。我不是专家所以我可能是错的,但它似乎是有道理的。

这不是“解决方案”中的答案,但我发现使用 W5100S 有 2k 缓冲区大小限制-EVB-Pico。事实上,如果我将 HTML 保持在 2k 以下,它就可以工作。事实证明,我实际上得到了 Matt Murphy 的建议,但 2k 限制是问题所在。看起来像是 hardware/library 的限制,对此不是很确定。

现在我会把我的 HTML 和 Javascript 缩小到最小,并用例如 textfixer.com 进一步压缩它。我想我可能会写一些 python 代码来做到这一点

也许下面的 link 中有解决方案,但目前我会尝试接受这些限制

Link: https://github.com/khoih-prog/EthernetWebServer/issues/7