TCP数据报如何到达客户端计算机?

问题描述 投票:0回答:2

我试图了解有关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;
}

以下两件事对我来说并不是很清楚

  1. response从哪里获取数据,从操作系统缓存或直接从网站获取数据?我还没有学过操作系统,这使我很难综合缓冲过程。
  2. 另外,理论上TCP会检查传输损耗,这会发生在哪里?当我进行套接字编程时,我没有看到任何关于传输丢失的处理程序,是否由socket自动处理?
c networking tcp
2个回答
1
投票

响应从哪里获取数据,来自操作系统的缓存或直接来自网站的数据?我还没有学过操作系统,这使我很难综合缓冲过程。

从网络设备(以太网卡,Wi-Fi适配器等)接收TCP数据包,并将其有效负载数据放入TCP / IP堆栈内的临时缓冲区。当程序调用recv()时,部分或全部数据将从临时缓冲区复制到程序缓冲区(response)。

除上述内容之外,TCP / IP堆栈不会对数据进行任何缓存。 (例如,如果Web浏览器想要缓存网页的本地副本,以便它不必再次下载它,那么Web应用程序级别的Web浏览器就可以在应用程序级别执行此操作; TCP / IP堆栈和操作系统不会自己这样做)

另外,理论上TCP会检查传输损耗,这会发生在哪里?当我进行套接字编程时,我没有看到任何关于传输丢失的处理程序,它是否由套接字自动处理?

它在TCP堆栈内透明地处理。特别是,每个TCP数据包都有一个校验和,序列号包含在其标头中,TCP栈检查它接收的每个数据包的序列号,以确保它与序列中的下一个数字匹配(相对于它从同一TCP流接收的前一个数据包)。如果它不是预期的next-packet-number,则TCP栈知道数据包以某种方式丢失,并且它通过向远程计算机发送请求重新发送丢弃的数据包来响应。请注意,TCP堆栈可能必须根据需要删除后续数据包,直到可以恢复最初预期的顺序,因为需要按照发送的确切顺序将有效负载数据传递到应用程序(即它不是允许在“较早”字节之前传送“稍后”字节,即使某些“较早”字节丢失并且必须重新传输)。


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';
© www.soinside.com 2019 - 2024. All rights reserved.