一个简单的TCP协议用于向服务器传输“大”数据文件

3

给那些负评者的信息: 请认真阅读问题,我正在处理一个小型嵌入式设备。如果您不熟悉这种设备的限制,请转到另一个问题,而不是进行负评!!!

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

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

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

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


2
HTTP POST在发送之前不需要将整个文件加载到内存中。 - user207421
正如我在问题中所述,我需要从头开始创建HTTP POST数据包,因为我正在使用一个没有实现HTTP协议的小型嵌入式设备。当然,你是正确的,但你可能是在谈论如何在拥有处理所有这些的API的强大操作系统上使用它。我正在使用原始的C编写代码,并且使用的RTOS没有这样的功能。 - Remixed123
1
解释得不够清楚。你仍然不必将整个文件加载到内存中,如果这是你使用HTTP POST的唯一反对理由,那么问题已经解决了。你也可以使用HTTP PUT。对那些试图帮助你的人粗鲁无礼并不是一个明智的策略。 - user207421
EJP,感谢您在回答我的问题方面所做的努力。但正如我在问题中所述,我只有TCP可用......对于协议栈上面的任何内容,我必须自己创建。也许我误解了您,您确实有解决方案,如果是这种情况,请告诉我需要做什么?我正在使用ANSI C进行编码,并拥有一个TCP套接字......从这里开始该怎么做? - Remixed123
1
我怎么对你不礼貌了?我在回复你时非常客气。至于那些投反对票的人,他们并不是在帮忙,只是投下反对票然后离开。如果他们想要帮忙,他们会提出问题以更好地理解。 - Remixed123
显示剩余2条评论
1个回答

8
我正在使用一台内存有限的小型嵌入式设备,并需要从该设备向服务器发送大文件。因此,我不能轻易地使用要求我在发送前将整个文件加载到内存中的HTTP POST。
不,POST并不要求如此。它所要求的只是您发送的HTTP Content-Length头与实际文件数据所发送的字节数相匹配。或者您可以使用HTTP 1.1的分块传输编码,它不使用Content-Length头(因此您不需要提前知道文件大小)。POST(或HTTP)没有任何关于您在代码中如何发送字节的概念。因此,您需要做的就是循环读取文件数据,使用适当大小的内存缓冲区,在每次读取后通过套接字发送该缓冲区的内容,直到达到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头和数据的字符串。
您不需要在单个字符串中一次发送所有内容。您可以根据需要将其分成多个字符串/发送。 TCP是一种流传输协议,它不关心您执行了多少次发送,只要发送的字节按正确的顺序即可。您甚至可以每次发送一个字节(尽管效率不高,但它仍然能正常工作)。
由于设备没有HTTP协议或其他协议可用作API,所以不需要。由于HTTP建立在TCP之上,并且您可以访问TCP套接字API,因此可以手动实现HTTP。
HTTP已经完全可以胜任这项任务。
协议需要相对简单,不使用太多内存资源,如果您知道一个专门针对小型嵌入式设备设计的库,那就更好了。最好在接收服务器上实现协议,该服务器最好运行.Net。
HTTP非常适合这个任务。

谢谢Remy。我非常感激您详细而深入的回答。我之所以问这个问题是因为我并没有完全理解一切,需要得到指导。您花时间纠正了我的假设并提供了答案。 - Remixed123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接