lwIP 调用远程服务器 API
lwIP call remote server API
这个问题会比较笼统,因为我什至还没有开始编码,只是想知道是否可以用 lwIP 实现我想要的。
我想要的是让我的嵌入式 STM32F769I-Disco 板调用网站 URL API,例如http://test.com/items/1,returns JSON,然后我想解析它。
由于 lwIP 实现了一个 TCP/IP 堆栈,这在理论上应该是可行的,还是我弄错了?
我还没有真正找到任何可以做到这一点的例子,或者我什至不知道如何搜索它。有什么有用的建议吗?
还有一个问题,我是否应该使用套接字连接而不是尝试调用 API url?如果我决定使用像 nanopb 这样的东西,我是否还需要 lwIP,或者我可以不用它吗?
从浏览 ST 网站来看,如果您愿意花一些时间来了解该平台,那么您所问的问题绝对是可能的。 ST 似乎发布了一个名为 STM32CubeF7. If you scroll down that link to the "User Manuals" section you'll see "UM1713: Developing applications on STM32Cube with lwIP TCP/IP stack" 的支持您的平台的软件开发堆栈,这听起来完全符合您的要求。
退一步说,正如您在问题中提到的,REST-ful 网站 API 通常实现为支持各种操作(GET、POST 等)的 HTTP URL。然而,HTTP 位于协议栈 TCP/IP 之上,并使用 TCP/IP 连接来传输数据 to/from 远程端点。 lwIP 似乎不提供 HTTP 客户端,因此您需要使用另一个库,但是有很多 GitHub 项目可以做到这一点。我最近写了一篇关于用 C++ 实现简单 HTTP 客户端的文章 blog post and codecast,它可能会提供一些见解并帮助阻止您自己动手。
关于你的最后一段,当谈到 "sockets" 时,人们通常指的是 TCP/IP(或 UDP/IP)套接字,所以是的,你仍然需要 lwIP。在这种情况下,Nanopb 将取代 HTTP。
从服务器检索数据涉及到使用 TCP 或 UDP,因此它不仅是 "theoretically possible",它是您的浏览器从 Web 服务器接收数据的实际方式:通过打开 TCP/IP 连接到服务器的端口 80.
UDP 不适用于从服务器接收数据,因为它是无连接的,并且不保证数据包会按顺序接收,或者根本不会接收。对于 TCP,它是 "all or nothing" - 要么您将按顺序接收所有数据包,要么套接字将在某个时刻关闭,因为发送方的缓冲区被未确认的数据包填满。
因此 HTTP 将使用 TCP/IP,这是肯定的,您需要执行以下几个步骤:
- 使用 lwip 为您的
www.test.com
网站创建 DNS 查找。
- 使用 lwip 打开一个 TCP/IP 到 IP 地址的连接,可能是端口 80。
- 将
recv
回调函数(以及其他函数)附加到 lwip,每当收到数据包时,Lwip 都会调用该回调函数。您还想知道套接字是否在对话期间关闭,因此请确保注册所有回调。
向端口 80 发送一个 HTTP request 字符串。您基本上是向打开的 TCP 套接字发送一个字符串。这可能很简单:
GET /items/1 HTTP/1.1
Host: www.test.com
<crlf>
最后的<crlf>
是一个空行,它标志着HTTP请求的结束。
您的 recv
函数将接受来自服务器的传入数据包,并将它们写入 FIFO 缓冲区以供进一步处理。不能保证您会在一个数据包中获得整个 HTTP 响应,所以不要指望一次性处理它们,除非负载真的很短,中间没有代理,并且您总体上感到幸运。
因此,您需要在传入数据到达时对其进行解析。其中一个 HTTP headers 会给你整个响应的长度,否则你将需要处理 chunked encoding。这是您可能从服务器获得的响应示例(在一个或多个 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]
}
注意 headers 和负载开始之间的空 new-line。
一旦你解析了所有 headers 并到达 JSON,那么你可能会使用现有的 C 库来解析 JSON,这也将可能需要一些工作才能理解。从开发的角度来看,用 Protocol Buffers 替换这最后一步可能是一个明智的想法(C 端的工作可能更少),但该协议的可移植性不如 JSON(尽管肯定更小)。
这个问题会比较笼统,因为我什至还没有开始编码,只是想知道是否可以用 lwIP 实现我想要的。
我想要的是让我的嵌入式 STM32F769I-Disco 板调用网站 URL API,例如http://test.com/items/1,returns JSON,然后我想解析它。
由于 lwIP 实现了一个 TCP/IP 堆栈,这在理论上应该是可行的,还是我弄错了?
我还没有真正找到任何可以做到这一点的例子,或者我什至不知道如何搜索它。有什么有用的建议吗?
还有一个问题,我是否应该使用套接字连接而不是尝试调用 API url?如果我决定使用像 nanopb 这样的东西,我是否还需要 lwIP,或者我可以不用它吗?
从浏览 ST 网站来看,如果您愿意花一些时间来了解该平台,那么您所问的问题绝对是可能的。 ST 似乎发布了一个名为 STM32CubeF7. If you scroll down that link to the "User Manuals" section you'll see "UM1713: Developing applications on STM32Cube with lwIP TCP/IP stack" 的支持您的平台的软件开发堆栈,这听起来完全符合您的要求。
退一步说,正如您在问题中提到的,REST-ful 网站 API 通常实现为支持各种操作(GET、POST 等)的 HTTP URL。然而,HTTP 位于协议栈 TCP/IP 之上,并使用 TCP/IP 连接来传输数据 to/from 远程端点。 lwIP 似乎不提供 HTTP 客户端,因此您需要使用另一个库,但是有很多 GitHub 项目可以做到这一点。我最近写了一篇关于用 C++ 实现简单 HTTP 客户端的文章 blog post and codecast,它可能会提供一些见解并帮助阻止您自己动手。
关于你的最后一段,当谈到 "sockets" 时,人们通常指的是 TCP/IP(或 UDP/IP)套接字,所以是的,你仍然需要 lwIP。在这种情况下,Nanopb 将取代 HTTP。
从服务器检索数据涉及到使用 TCP 或 UDP,因此它不仅是 "theoretically possible",它是您的浏览器从 Web 服务器接收数据的实际方式:通过打开 TCP/IP 连接到服务器的端口 80.
UDP 不适用于从服务器接收数据,因为它是无连接的,并且不保证数据包会按顺序接收,或者根本不会接收。对于 TCP,它是 "all or nothing" - 要么您将按顺序接收所有数据包,要么套接字将在某个时刻关闭,因为发送方的缓冲区被未确认的数据包填满。
因此 HTTP 将使用 TCP/IP,这是肯定的,您需要执行以下几个步骤:
- 使用 lwip 为您的
www.test.com
网站创建 DNS 查找。 - 使用 lwip 打开一个 TCP/IP 到 IP 地址的连接,可能是端口 80。
- 将
recv
回调函数(以及其他函数)附加到 lwip,每当收到数据包时,Lwip 都会调用该回调函数。您还想知道套接字是否在对话期间关闭,因此请确保注册所有回调。 向端口 80 发送一个 HTTP request 字符串。您基本上是向打开的 TCP 套接字发送一个字符串。这可能很简单:
GET /items/1 HTTP/1.1 Host: www.test.com <crlf>
最后的
<crlf>
是一个空行,它标志着HTTP请求的结束。您的
recv
函数将接受来自服务器的传入数据包,并将它们写入 FIFO 缓冲区以供进一步处理。不能保证您会在一个数据包中获得整个 HTTP 响应,所以不要指望一次性处理它们,除非负载真的很短,中间没有代理,并且您总体上感到幸运。因此,您需要在传入数据到达时对其进行解析。其中一个 HTTP headers 会给你整个响应的长度,否则你将需要处理 chunked encoding。这是您可能从服务器获得的响应示例(在一个或多个 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] }
注意 headers 和负载开始之间的空 new-line。
一旦你解析了所有 headers 并到达 JSON,那么你可能会使用现有的 C 库来解析 JSON,这也将可能需要一些工作才能理解。从开发的角度来看,用 Protocol Buffers 替换这最后一步可能是一个明智的想法(C 端的工作可能更少),但该协议的可移植性不如 JSON(尽管肯定更小)。