这不是一个家庭作业问题,我保证。
我正在编写一个时间序列数据库实现作为学习C的方法。
我有一个我写过的客户/服务器对。服务器当前是侦听端口上的套接字的echo服务器。客户端连接到该端口并向其发送输入行。它使用readline
来获取输入,send
到客户端套接字,recv
是来自客户端套接字的一行,并将该行打印到终端。冲洗,重复。客户端从EOF
获得recv
时返回,此时它知道连接已关闭。
问题是readline
正在阻止,这样如果服务器进程被终止,即我SIGINT
,则客户端仍然在readline
上阻塞。直到send
之后,recv
为EOF
,它才知道服务器已经消失。
我想要发生的事情是,如果EOF
上有recv
并立即退出,客户就会收到信号。
我认为我需要做的是为网络客户端(pthreads
和send
)创建3 recv
- 2,为终端创建1 。终端呼叫readline
并阻止。它接受输入,然后使用pthread_cond_t
发信号通知等待网络客户端send
线程发送。网络客户端recv
线程始终recv
,这将阻止。如果它是EOF
,它会引发SIGINT
,pthread_kill
所有3个线程的处理程序,fprintf
类似于"连接由服务器关闭。& #34;,然后调用exit
(是的,我知道exit
会终止所有线程 - 这是一个清洁工作,看看我是否理解C)。
这是适当的方法吗?显然,网络客户终端一直这样做。什么是正确的方法?
答案 0 :(得分: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;
}
答案 1 :(得分:1)
之前已经回答过这个问题。我得到了Stevens,第5章建议将readline
调用与套接字read
交错以查找EOF
。我对libreadline
和select
/ poll
进行了Google搜索,并看到了这一点:
Interrupting c/c++ readline with signals
有一种方法可以使用交错I / O,因此libreadline
不会阻止:
http://www.delorie.com/gnu/docs/readline/rlman_41.html
感谢@ arayq2和@ G--建议史蒂文斯!