从套接字读取时如何处理阻塞read()调用?

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

我正在用C语言编写一个简单的IRC客户端程序用于自学,并且当从套接字文件描述符调用读取时,我无法理解read()函数的行为。

以下代码段工作并打印与运行相同的输出

$ echo "NICK gertrudes\r\nUSER a 0 * d\r\n" | nc chat.freenode.net 6667

在终端,这与我的程序打印到目前为止:

while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
    printf("\nloop\n");
    buffer[n] = '\0';
    if (fputs(buffer, stdout) == EOF)
        error("fputs");
}
if (n < 0)
    error("reading from socket");

printf("out of the loop\n");

我无法理解的是为什么程序永远不会进入最后的printf调用,而是坐在那里,就像从服务器等待更多。这是否意味着最后一个回复长于0并且IRC服务器在发送另一个命令之前不会发送任何新内容?

如果是这样(冒着离开这里的话题),并且read()正在阻塞,那么在程序等待该调用返回时,我会在哪里编写向服务器发送命令的逻辑?

c sockets irc
2个回答
1
投票

我无法理解的是为什么程序永远不会进入最后的printf调用,而是坐在那里,好像等待来自服务器的更多。

它正在等待来自服务器的更多内容。当对等体断开连接时,qazxsw poi将返回零,而不是之前。


0
投票

尽管你的程序不完整,但你有一些错误的假设。我们在您的代码中对这些进行评论。

read()
  • 如果你打算用while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) { 字节来完成它,那么阅读sizeof(buffer)-1会很好,但是想想你可以从套接字接收\0,如果你想成为一般的,不要以为你总是在阅读文本。许多安全漏洞都来自这样的错误。程序员(错误地)假定数据是ascii文本,并且有人利用缓冲区溢出(不是这种情况)或非法的东西,提供大量空字符以使其失败。 \0
  • 这是一个非常常见的错误...你习惯于看到当你将printf("\nloop\n"); buffer[n] = '\0'; if (fputs(buffer, stdout) == EOF) 放在缓冲区的末尾时,stdio会在看到它之后立即将所有内容打印到最后一个缓冲区。好吧,为了实现这一点,\n检查描述符是否与终端相关联(通过stdio调用,或调用ioctl(2))。对于套接字不再适用,因此可能已将缓冲区复制到stdio缓冲区,并且stdio正在等待缓冲区填充,或者在调用isatty(3)以通过它发送所有数据之前使用fflush(3)显式刷新缓冲区。 write(2)
  • 此时做一个 error("fputs"); ,所以你确定你的所有数据都被发送到同行,然后继续,或者根本不使用stdio(使用简单的fflush(stdout);调用,直到你足够精通准备一个write(2)s的线程套接字一旦准备好接受更多数据就可以提供更多数据) select(2)
© www.soinside.com 2019 - 2024. All rights reserved.