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

时间:2018-03-04 00:43:36

标签: c sockets irc

我在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()正在阻塞,那么在程序等待该调用返回时,我会在哪里编写向服务器发送命令的逻辑? / p>

2 个答案:

答案 0 :(得分:1)

  

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

从服务器 等待更多。当对等体断开连接时,read()将返回零,而不是之前。

答案 1 :(得分:0)

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

while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
  • 如果您计划使用sizeof(buffer)-1字节填写\0,最好先阅读\0,但认为您可以接收来自printf("\nloop\n"); buffer[n] = '\0'; if (fputs(buffer, stdout) == EOF) 套接字,如果你想成为一般,不要以为你总是在阅读文本。许多安全漏洞都来自这样的错误。程序员(错误地)假设数据是ascii文本,有人利用缓冲区溢出(不是这种情况)或非法的东西,提供大量空字符以使其失败。

    \n
  • 这是一个非常常见的错误 ...你习惯看到当你在缓冲区末尾放置一个stdio时,stdio将打印出所有内容,直到最后一个缓冲区一见到它。好吧,为了实现这一点,ioctl(2)检查描述符是否与终端相关联(通过isatty(3)调用或调用fflush(3))。对于套接字不再适用,因此可能已将缓冲区复制到stdio缓冲区,stdio正在等待缓冲区填充,或者在调用write(2)发送之前使用 error("fputs"); 显式刷新缓冲区它上面的所有数据。

    fflush(stdout);
  • 此时执行write(2),因此您可以确保在继续之前将所有数据发送给对等方,或者根本不使用stdio(使用简单的select(2)来电,直到你足够精通准备一个} if (n < 0) error("reading from socket"); printf("out of the loop\n"); 在套接字上的线程,以便在它准备接受更多数据后立即提供更多数据)

    import matplotlib, multiprocessing
    
    matplotlib.use('TkAgg')
    import matplotlib.pyplot as plt
    
    def plot(): 
       import matplotlib
       fig = matplotlib.pyplot.figure()
       fig.show()    
    
    plot()
    multiprocessing.set_start_method('spawn') 
    p = multiprocessing.Process(target=plot, args=())
    p.start() 
    raw_input()