lwIP 调用远程服务器 API

xtr*_*nch 1 embedded stm32 lwip stm32f7

这个问题相当笼统,因为我还没有开始编码,只是想知道是否有可能用 lwIP 实现我想要的。

我想要的是让我的嵌入式 STM32F769I-Disco 板调用网站 URL API,例如http://test.com/items/1,它返回 JSON,然后我想解析它。

由于 lwIP 实现了 TCP/IP 堆栈,这在理论上应该是可能的,还是我错了?

我还没有真正找到任何可以做到这一点的例子,或者我什至不知道如何搜索它。任何有用的指针?

问题也是,我是否应该使用套接字连接而不是尝试调用 API url?如果我决定使用 nanopb 之类的东西,我还需要 lwIP,还是可以不用它?

Gro*_*roo 6

无论涉及从服务器检索数据,都涉及使用 TCP 或 UDP,因此它不仅“理论上可能”,而且是浏览器从 Web 服务器接收数据的实际方式:通过打开到服务器端口 80 的 TCP/IP 连接。

UDP 对于从服务器接收数据是不切实际的,因为它是无连接的,并且不能保证数据包会按顺序接收,或者根本不会被接收。对于 TCP,它是“全有或全无”——要么您将按顺序接收所有数据包,要么当发送方的缓冲区充满未确认的数据包时,套接字将在某个时刻关闭。

因此,HTTP 将使用 TCP/IP,这是肯定的,您需要执行以下几个步骤:

  1. 使用 lwip 为您的www.test.com网站创建 DNS 查找。
  2. 使用 lwip 打开到 IP 地址的 TCP/IP 连接,可能是端口 80。
  3. recv回调函数(以及其他)附加到 lwip,每当接收到数据包时,Lwip 都会调用该回调函数。您还想知道套接字是否在对话期间关闭,因此请确保注册所有回调。
  4. 向端口 80发送一个HTTP 请求字符串。您基本上是向打开的 TCP 套接字发送一个字符串。这可能很简单:

    GET /items/1 HTTP/1.1
    Host: www.test.com
    <crlf>
    
    Run Code Online (Sandbox Code Playgroud)

    最后<crlf>是一个空行,它标志着 HTTP 请求的结束。

  5. 您的recv函数将接受来自服务器的传入数据包,并将它们写入 FIFO 缓冲区以供进一步处理。无法保证您将在单个数据包中获得整个 HTTP 响应,因此不要期望一次性处理它们,除非有效负载非常短,两者之间没有代理,并且您总体上感觉很幸运。

  6. 因此,您将需要在传入数据到达时对其进行解析。其中一个 HTTP 标头将为您提供整个响应的长度,或者您需要处理分块编码。这是您可能从服务器获得的响应示例(在一个或多个 TCP 数据包中):

    HTTP/1.1 200 OK
    Date: Mon, 23 Aug 2017 22:38:34 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Encoding: UTF-8
    Content-Length: 18
    
    { 
        "value":5, 
        "something_else": [0, 1, 2] 
    }
    
    Run Code Online (Sandbox Code Playgroud)

    请注意标头和有效负载开头之间的空换行符。

  7. 一旦你解析了所有的头并得到了 JSON,那么你可能会使用现有的 C 库来解析 JSON,这也可能需要一些工作来理解。从开发的角度来看,用 Protocol Buffers 替换这最后一步可能是一个明智的想法(C 端的工作可能更少),但该协议的可移植性将不如 JSON(尽管肯定更小)。

  • @Nirri:如果您可以连接到普通的 TCP/IP 套接字,您绝对可以创建一个比 HTTP 更简单的协议。拥有一条以特定 cookie、长度开始,然后包含数据,并以 crc 结束的消息会更容易(从嵌入式编程的角度来看),并且避免必须处理 HTTP 的各种细微差别。但是如果您的服务器端已经运行了某种 Web 服务,那么您可能需要走这条路(也许您还可以在 lwip 之上找到一个轻量级的 HTTP 堆栈,我不知道)。 (2认同)