【问题标题】:How does the read function in c knows when to stop reading from a client socket?c 中的 read 函数如何知道何时停止从客户端套接字读取?
【发布时间】:2015-07-09 16:50:56
【问题描述】:

我用 C 语言编写了一个客户端和一个服务器来测试与套接字的数据传输。 基本上,服务器等待连接,接受它并向客户端文件描述符调用read() 函数,如下所示:

while (read(clisock_fd, client_message, 20000) > 0) {
    puts(client_message);
}

在客户端程序中,我只发送一条带有write()的消息,如下所示:

write(sockfd, my_message, strlen(my_message));

我想不通的是,如果 write() 函数发送 8 个字节,而 read() 函数读取它们一次,它怎么知道是时候停止等待任何其他消息了?

例如,如果我发送 3000 个字节,read 函数读取 1448 个字节,然后它会读取其余的字节,然后它就知道它已经结束并停止。怎么样?

【问题讨论】:

  • 没有更多数据可以从通信堆栈缓冲区中读取,因此 read() 调用阻塞,直到 nic 中断,随后驱动程序运行,提供更多数据,(或连接关闭由对等方,或发生错误)。

标签: c sockets


【解决方案1】:

它在读取至少一个字节后从不等待。你的硬件有缓冲区,你的内核有缓冲区。这 8 个字节立即可供用户空间进程使用。事实上,它们是在一个以太网帧中传输的,因为在写入端也有缓冲区。

【讨论】:

    【解决方案2】:

    似乎这两个问题:

    • 我想不通的是,如果 write() 函数发送 8 个字节,而 read() 函数读取它们一次,它怎么知道是时候停止等待任何其他消息了?

    • 例如,如果我发送 3000 个字节,read() 函数会读取 1448 个字节,然后它会读取其余的字节,然后它就知道它已经结束并停止。怎么样?

    对提供的源代码有相同的答案。

    相应手册页的相关部分:

    返回值

    成功时,返回读取的字节数(零表示文件结束),文件位置提前该数字。如果此数字小于请求的字节数,则不是错误;例如,这可能是因为现在实际可用的字节较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为 read() 被中断信号。出错时,返回 -1,并适当设置 errno。在这种情况下,未指定文件位置(如果有)是否更改。

    -- read(2).

    因此,对于给定的源代码,当read() 函数返回非正数(零或负数)时,while 循环的条件变为false。 更有可能在发送“消息”后,发送者关闭连接(close() 函数调用)并且接收者“知道消息结束”,因为接收者的 read() 函数调用返回零。

    注意事项

    1. 请介绍检查read()write() 函数调用的返回值。这些函数不保证一次读取/写入指定数量的字节(一次调用)。

    2. 文章TCP/IP client-server application: exchange with string messages, Sergey Brunov 可能有用。文章描述了“消息边界”的概念,并提供了一个实现的例子。

    【讨论】:

      【解决方案3】:

      规则很简单。对于阻塞套接字,read 将等待直到有一些数据要读取,可能是 1 字节或 1MB。然后内核将复制内核在其内部缓冲区中的尽可能多的数据,或请求的字节数,以较小者为准。并且read 将在此之后立即返回,而无需等待进一步的数据。读取的返回值报告实际读取的字节数。

      您的程序可以正常工作,因为您的连接速度很快,而且您正在以合理的方式编写代码。但是,您可能会发现,一旦您在阅读世界中推出您的程序,您的程序就会崩溃。这是因为您的 read 可能只返回字符串的一部分而没有空终止符。当您调用 puts 时,缓冲区将溢出,您可能会崩溃(或更糟)。

      因此,如果在您的情况下,您的协议规定数据流必须以空值结尾,您将需要解析返回的数据以查看它是否包含空值。出于这个原因,我更喜欢在实际发送数据之前指定要发送的数据长度的协议。让处理更简单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多