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

时间:2018-05-01 01:59:44

标签: c networking tcp

我试图了解一些有关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自动处理?

2 个答案:

答案 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';