【问题标题】:A Simple TCP Protocol to Transfer a "Large" Data File to a Server将“大”数据文件传输到服务器的简单 TCP 协议
【发布时间】:2015-05-01 17:28:33
【问题描述】:

给反对者的信息:请阅读这个问题,我正在开发一个小型嵌入式设备。如果您不熟悉此类设备的局限性,请转到另一个问题而不是投反对票!!!!

我正在使用内存有限的小型嵌入式设备,我需要从该设备向服务器发送一个大文件。因此,我不能轻松使用 HTTP POST,这需要我在发送之前将整个文件加载到内存中。

嵌入式设备具有 UDP 和 TCP 套接字,但例如发送 HTTP POST,我需要创建一个包含 HTTP HEADERS 和数据的字符串。由于设备没有 HTTP 协议或其他可用作 API 的协议。

有人可以推荐一种协议,我可以使用它来执行“流式传输”或将数据部分发送到服务器的过程吗?

该协议需要相对简单并且不占用太多内存资源,如果您知道为小型嵌入式设备设计的库,那也很好。该协议还应该易于在接收服务器上实现,最好运行 .Net

【问题讨论】:

  • HTTP POST 不要求您在发送前将整个文件加载到内存中。
  • 正如我的问题中所述,我需要从头开始创建 HTTP POST 数据包,因为我使用的是没有实现 HTTP 协议的小型嵌入式设备。当然,您是对的,但您可能在谈论如何在强大的操作系统上使用它,该操作系统具有可处理所有这些的 API。我正在使用原始 C 进行编码,其 RTOS 不提供此类功能。
  • 什么也没解释。您仍然不必将整个文件加载到内存中,如果这是您对使用 HTTP POST 的唯一反对意见,那么问题就解决了。您也可以使用 HTTP PUT。对试图帮助你的人无礼不是一个理性的策略。
  • EJP,感谢您为回答我的问题所做的努力。但正如我的问题所述,我只有 TCP 可用....对于协议堆栈上高于此的任何内容,我必须创建我自己。也许我误解了你,你实际上有一个解决方案,如果是这样,那么请你给我解释一下我需要做什么?我正在使用 ANSI C 进行编码,并且有一个 TCP 套接字……我该去哪里?
  • 我对你有多粗鲁?我对你的回复很有礼貌。至于否决的选民,他们并没有试图提供帮助,他们只是投反对票并继续前进。如果他们想提供帮助,他们会提出一个问题以便更好地理解。

标签: sockets tcp protocols network-protocols


【解决方案1】:

我正在使用内存有限的小型嵌入式设备,我需要从该设备向服务器发送一个大文件。因此我不能轻易使用 HTTP POST,这需要我在发送之前将整个文件加载到内存中

不,POST 不需要。它所要求的只是您发送的 HTTP Content-Length 标头与您为实际文件数据发送的字节数相匹配。或者您可以使用 HTTP 1.1 的 chunked 传输编码,它不使用 Content-Length 标头(因此您无需提前知道文件大小)。 POST(或 HTTP,就此而言)没有您在代码中发送字节的 HOW 概念。所以所要做的就是在循环中读取文件数据,使用适当大小的内存缓冲区,在每次读取后通过套接字发送该缓冲区的内容,直到您点击 EOF。

例如(伪代码):

sckt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
connect(sckt, "hostname", 80)
send(sckt, "POST /resource HTTP/1.0\r\n")
send(sckt, "Content-Type: application/octet-stream\r\n"); // or the actual file type
send(sckt, "Content-Length: " + string(the file size) + "\r\n")
send(sckt, "\r\n")

byte buffer[256] // use whatever buffer size is appropriate for your device
do
{
    numread = read(file, buffer, sizeof(buffer));
    if (numread <= 0) break;
    send(sckt, buffer, numread);
}
while (true);

read HTTP response from sckt ...

或者:

sckt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
connect(sckt, "hostname", 80)
send(sckt, "POST /resource HTTP/1.1\r\n")
send(sckt, "Content-Type: application/octet-stream\r\n"); // or the actual file type
send(sckt, "Transfer-Encoding: chunked\r\n")
send(sckt, "\r\n")

byte buffer[256] // use whatever buffer size is appropriate for your device
char hex[12]
do
{
    numread = read(file, buffer, sizeof(buffer));
    if (numread <= 0) break;

    sprintf(hex, "%x", numread);
    send(sckt, string(hex) + "\r\n")
    send(sckt, buffer, numread)
    send(sckt, "\r\n")
}
while (true);

send(sckt, "0\r\n");
send(sckt, "\r\n");

read HTTP response from sckt ...

即使是功能强大的台式电脑也必须这样做,因为通常无法将整个文件一次放入内核缓冲区,因此必须相应地循环发送。

嵌入式设备有 UDP 和 TCP 套接字,但是例如发送 HTTP POST,我需要创建一个包含 HTTP HEADERS 和数据的字符串。

不要必须在一个字符串中一次发送所有内容。您可以根据需要将其分解为多个字符串/发送。 TCP 是一种流传输,它不关心您执行了多少次发送,只要您发送的字节顺序正确。您可以一次发送 1 个字节(尽管这不是很有效,但它会起作用)。

由于设备没有 HTTP 协议或其他可用作 API 的协议。

不需要。由于 HTTP 位于 TCP 之上,并且您可以访问 TCP 套接字 API,因此您可以手动实现 HTTP。

有人可以推荐一种协议,我可以使用它来执行“流式传输”或将数据部分发送到服务器的过程吗?

HTTP 已经做到了这一点。

该协议需要相对简单并且不占用太多内存资源,如果您知道为小型嵌入式设备设计的库,那也很好。该协议还应该易于在接收服务器上实现,最好运行 .Net

HTTP 非常适合。

【讨论】:

  • 谢谢雷米。我非常感谢您详细而有见地的回复。我问这个问题的原因是因为我确实完全理解了一切并且需要被告知。您花时间纠正了我的假设并提供了答案。
猜你喜欢
  • 2021-02-08
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 2012-08-26
  • 2017-03-28
  • 2011-02-18
  • 1970-01-01
相关资源
最近更新 更多