【问题标题】:C - Signaling to another thread to cleanup and exitC - 向另一个线程发出信号以清理并退出
【发布时间】:2014-06-07 05:03:56
【问题描述】:

我保证,这不是作业问题。

我正在编写时间序列数据库实现作为学习 C 的一种方式。

我已经编写了一个客户端/服务器对。该服务器当前是一个监听端口上的套接字的回显服务器。客户端连接到该端口并向其发送输入行。它使用readline 获取输入,sends 将其发送到客户端套接字,recvs 来自客户端套接字的一行,并将该行打印到终端。冲洗,重复。客户端在从recv 获得EOF 时返回,此时它知道连接已关闭。

问题是readline被阻塞了,所以如果服务器进程被杀死,即我SIGINT它,客户端仍然阻塞readline。直到sends,然后是recvs 和EOF,它才会知道服务器已经消失。

想要发生的事情是,如果recv 上有EOF,客户端会收到信号并立即退出。

认为我需要做的是为网络客户端(sendrecv)创建 3 个pthreads - 2,为终端创建 1 个。终端调用readline 并阻止。它接受输入,然后使用pthread_cond_t 向等待的网络客户端send 线程发送信号。网络客户端recv线程不断recving,会阻塞。如果它是EOF,它会引发SIGINTpthread_kills 所有 3 个线程的处理程序,fprintfs 类似于“连接被服务器关闭”,并调用exit(是的,我知道exit 无论如何都会终止所有线程 - 这是一个清洁练习,看看我是否理解 C)。

这是合适的方法吗?显然,网络客户端一直都在这样做。什么是正确的方法?

【问题讨论】:

  • 没有一种正确的方法。经典参考是 Rich Stevens 的 UNIX Network Programming
  • @arayq2 谢谢!我去看看!
  • "它使用 readline 来获取输入..." ""是谁,客户端还是服务器?
  • 并且:一个不会发送“到套接字”而是“通过”一个套接字“”一些目的地(这里是客户端服务器),因为大多数情况下套接字是双向使用的。

标签: c sockets pthreads signals


【解决方案1】:

如果我对您的理解正确,您想在readline 期间退出,即在您的write()/send() 之前,当服务器死机时。你的方法很好。如果服务器死机,您将捕获的唯一方法是当您尝试 write()/send() 时,您将得到一个 SIGPIPE ,这将导致其后立即退出。因为默认情况下,除非有数据要发送或确认,否则不会在连接上发送数据包。因此,如果您只是在等待来自对等方的数据,则无法判断对等方是否已经默默地离开了,或者只是还没有准备好发送/接收更多数据。因此,您需要在一个单独的线程中为SIGPIPE 提供一些轮询器,并在获得它时退出。您可以使用这个readline 函数来帮助您开始检查。

/**
 * Simple utility function that reads a line from a file descriptor fd, 
 * up to maxlen bytes -- ripped from Unix Network Programming, Stevens.
 */
int
readline(int fd, char *buf, int maxlen)
{
    int n, rc;
    char c;

    for (n = 1; n < maxlen; n++) {
    if ((rc = read(fd, &c, 1)) == 1) {
        *buf++ = c;
        if (c == '\n')
        break;
    } else if (rc == 0) {
        if (n == 1)
        return 0; // EOF, no data read
        else
        break; // EOF, read some data
    } else
        return -1; // error
    }

    *buf = '\0'; // null-terminate
    return n;
}

【讨论】:

  • 这是有道理的。 FWIW,一位同事说为每个字符调用read 效率非常低,因为每个调用都必须被内核捕获。我不知道这是不是真的,如果是的话,会产生什么影响。无论如何,我实际上是在使用 libreadline 来获得内置的 ctrl 字符功能。我去看看史蒂文斯。
【解决方案2】:

这个问题之前已经回答过了。我得到了 Stevens,第 5 章建议将readline 调用与套接字read 交错以查找EOF。我在 Google 上搜索了 libreadlineselect/poll 并看到了这个:

Interrupting c/c++ readline with signals

有一种方法可以使用交错 I/O,所以 libreadline 不只是阻塞:

http://www.delorie.com/gnu/docs/readline/rlman_41.html

感谢 @arayq2 和 @G-- 建议 Stevens!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 2015-09-27
    • 1970-01-01
    • 2019-02-12
    • 2014-09-18
    • 1970-01-01
    • 2018-06-30
    相关资源
    最近更新 更多