繁体   English   中英

recv 在套接字编程中是如何工作的?

[英]How does recv work in socket programming?

我试图从高层次上理解 recv() 。 所以 recv 以“块”的形式获取数据,但我仍然不知道它是如何被精确处理的。 例子:

char buffer[1000]; 
int received= recv(sock, buffer, sizeof(buffer), 0)

这是否意味着如果我正在接收一个大文件,缓冲区,如果通过 sock 连接可能会反映它在接收变量中存储了 500 个字节,然后在循环中接收另外 300 个字节,所有 800 个字节的数据将被存储在循环结束时在缓冲区中(除非考虑到,否则丢失在接收到的变量中),或者缓冲区是否需要一个指针来跟踪它上次接收数据的位置以将其存储在下一次迭代中?

recv没有上下文。 它只知道它有一些要写入的地址(指针)和一些最大大小 - 然后它会尝试这个。 它总是从给定的地址开始写入。 例如,如果希望在某些先前接收到的数据之后添加数据,则可以简单地将指针指向先前数据之后的位置,而不是缓冲区的开头。 当然,应该调整允许读取的最大大小以不溢出缓冲区。

您问“recv() 是如何工作的?”,因此可能值得简要研究一个更简单的 function ,它基本上做同样的事情 - read()

recv()的操作方式与read() function 大致相同。 主要区别在于recv()允许您在最后一个参数中传递标志 - 但无论如何您都不会使用这些标志。

我的建议是 - 在尝试使用recv()从网络套接字读取之前 - 在纯文本文件上练习使用read()

两个函数都返回读取的字节数——除非出现错误,在这种情况下它们将返回 -1。 您应该始终检查这种情况 - 并妥善处理。

这两个函数也可以返回少于请求的字节数。 recv()的情况下 - 并从套接字读取 - 这可能是因为另一端还没有发送所有需要的数据。 在从文件读取的情况下 - 使用read() - 这可能是因为您已到达文件末尾。

反正...

您将需要跟踪缓冲区中的当前偏移量- 并在每次读取时更新它。 所以声明一个文件范围的变量offset

static off_t offset; static char buffer[1000];

然后 - 当你的“循环”运行时 - 每次读取后增加偏移量......

while (1) {
    size_t max_len = sizeof(buffer) - offset;
    ssize_t count = recv(sock, buffer+offset, max_len, 0);
    if (count == -1) {
        switch (errno) {
            case EAGAIN:
              usleep(20000);
              break;
            default:
              perror("Failed to read from socket");
              close(sock);
              break;
        }
    }
    if (count == 0) {
        puts("Looks like connection has been closed.");
        break;
    }
    offset += count;
    if (offset >= expected_len) {
        puts("Got the expected amount of data. Wrapping up ...");
    }
}

笔记:

  • 使用这种方法,您要么需要事先知道预期的数据量,要么使用特殊的分隔符来标记消息的结尾
  • max_len变量指示缓冲区中还剩下多少空间 - 并且(也许不用说)您不应该尝试读取比这更多的字节
  • recv()命令的目标是buffer+offset - 不是buffer
  • 如果recv()返回零,AFAIK 这表明另一端已执行“有序关闭”。
  • 如果recv()返回-1,你真的需要检查返回码。 EAGAIN不是致命的 - 只是意味着您需要再试一次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM