我试图了解一些有关TCP数据传输的概念。
假设我们使用套接字(C
)发送和接收GET HTTP
网站请求。关于接收端,我所看到的是下面的实现。基本上,创建response
缓冲区并迭代填充。
memset(response, 0, sizeof(response));
total = sizeof(response)-1;
received = 0;
while (received < total) {
bytes = recv(sockfd, response + received, total - received, 0);
if (bytes < 0)
error("ERROR reading response from socket");
if (bytes == 0)
break;
received += bytes;
}
以下两件事对我来说并不是很清楚
response
从哪里获取数据,从操作系统缓存或直接从网站获取数据?我还没有学过操作系统,这使我很难综合缓冲过程。socket
自动处理?答案 0 :(得分:1)
响应从哪里获取数据,从OS缓存数据或数据 直接来自网站?我还没有学过操作系统 这让我很难全面地完成缓冲过程。
从网络设备(以太网卡,Wi-Fi适配器等)接收TCP数据包,并将其有效负载数据放入TCP / IP堆栈内的临时缓冲区。当程序调用{{1}}时,部分或全部数据将从临时缓冲区复制到程序缓冲区(//Using streams provides a neat solution.
// this will give you {1.3, 3.5, 98.342}
String input = "1.3::3.5::98.342";
double[] arr = Arrays.stream(input.split("::")).mapToDouble(Double::parseDouble).toArray();
)。
TCP / IP堆栈不会执行除上述内容之外的任何数据缓存。 (例如,如果Web浏览器想要缓存网页的本地副本,以便它不必再次下载它,那么Web应用程序级别的Web浏览器就可以在应用程序级别执行此操作; TCP / IP堆栈和操作系统本身不会这样做)
另外,理论上TCP会检查传输损耗,在哪里 这发生了吗?当我进行套接字编程时,我没有看到任何 有关传输损耗的处理程序,它是否自动处理 插座?
它在TCP堆栈内透明地处理。特别是,每个TCP数据包都有一个校验和,序列号包含在其标头中,TCP栈检查它接收的每个数据包的序列号,以确保它与序列中的下一个数字匹配(相对于它从同一TCP流接收的前一个数据包)。如果它不是预期的next-packet-number,则TCP栈知道数据包以某种方式丢失,并且它通过向远程计算机发送请求重新发送丢弃的数据包来响应。请注意,TCP堆栈可能必须根据需要删除后续数据包,直到可以恢复最初预期的顺序,因为需要按照发送的确切顺序将有效负载数据传递到应用程序(即它不是允许在“较早”字节之前传递“稍后”字节,即使某些“较早”字节丢失并且必须重新传输)。
答案 1 :(得分:0)
响应从哪里获取数据,来自操作系统的缓存?我还没有学过操作系统,这使我很难全面地完成缓冲过程。
也许,也许不是,您不关心,因为您是该功能的用户。所有这些都由TCP socket protocol保证。但是,如果您忘记读取套接字,则套接字数据将已满。您可以排队的数据有限制。
另外,理论上TCP会检查传输损耗,这会发生在哪里?当我进行套接字编程时,我没有看到任何有关传输丢失的处理程序,它是否由套接字自动处理?
是。不要担心这件事。美丽,不是吗?
关于您的代码,我预计会遇到一些问题:
// not necessary as you should only read the bytes affected by recv()
// memset(response, 0, sizeof(response));
// should declare total and received here
size_t total = sizeof(response) - 1;
size_t received = 0;
while (received < total) {
// should declare byte only here
ssize_t bytes = recv(sockfd, response + received, total - received, 0);
if (bytes < 0)
error("ERROR reading response from socket");
if (bytes == 0)
break;
received += (size_t)bytes;
}
// as you want read a string don't forget
response[received] = '\0';