【发布时间】:2013-07-23 05:18:55
【问题描述】:
我有一个用 C 编写的多线程服务器,每个客户端线程看起来像这样:
ssize_t n;
struct request request;
// Main loop: receive requests from the client and send responses.
while(running && (n = recv(sockfd, &request, sizeof(request), 0)) == sizeof(request)) {
// Process request and send response.
}
if(n == -1)
perror("Error receiving request from client");
else if(n != sizeof(act))
fprintf(stderr, "Error receiving request from client: Incomplete data\n");
// Clean-up code.
在某些时候,客户端满足必须断开连接的特定条件。如果客户端定期发送请求,这很好,因为它可以在响应中被告知断开连接;然而,有时客户端需要很长时间才能发送请求,因此客户端线程最终会在 recv 调用中阻塞,并且客户端在下一个请求/响应之前不会断开连接。
当客户端线程在recv 调用中阻塞时,是否有一种干净的方法可以断开客户端与另一个线程的连接?我尝试了close(sockfd),但这会导致错误Error receiving request from client: Bad file descriptor 发生,这确实不准确。
或者,有没有更好的方法让我在这里处理错误?
【问题讨论】:
-
@DrewMcGowen 谢谢,我曾寻找类似的线程,但我设法错过了那个。仍然不确定这是完全相同的问题,因为完全杀死线程并不是我真正认为干净的。
-
@DanielGibbs:“kill”是一个用于发送信号的函数的不幸名称。也许在另一个现实中,
pthread_kill()被称为pthread_send_signal()。但是,是的,您可以使用信号彻底中断recv()。 -
@MartinJames:这个解决方案是绝对错误的。它有极其危险的比赛条件。假设
recv被信号中断,close在信号处理程序运行时发生。信号处理程序返回后,recv在相同的 fd 编号上重新启动。如果幸运的话,fd 是无效的,它会返回EBADF。但是如果你很不走运,另一个线程打开了一个新的 fd,得到了相同的 fd 编号,而你只是窃取了另一个线程的输入。 -
然而,
close方法的安全替代方法是使用shutdown。基本上,它会半关闭或完全关闭 TCP 连接,但会保留文件描述符。
标签: c multithreading sockets pthreads posix