【发布时间】:2018-04-17 22:19:21
【问题描述】:
我知道一个基于服务器和各种客户端的应用程序,但我遇到了发送命令的问题。 每当我在客户端执行 ctrl+c 时,发送操作都会杀死正在运行的线程和正在运行的进程(为了有多个客户端,我设置了一个线程一)。
如果客户端正确结束(执行关闭套接字),服务器不会死,但是当我在客户端上使用 ctrl+c 组合时,两者都会退出。
如何防止发送命令出现这种行为?
提前致谢
【问题讨论】:
我知道一个基于服务器和各种客户端的应用程序,但我遇到了发送命令的问题。 每当我在客户端执行 ctrl+c 时,发送操作都会杀死正在运行的线程和正在运行的进程(为了有多个客户端,我设置了一个线程一)。
如果客户端正确结束(执行关闭套接字),服务器不会死,但是当我在客户端上使用 ctrl+c 组合时,两者都会退出。
如何防止发送命令出现这种行为?
提前致谢
【问题讨论】:
查看beej's guide to signals。您需要捕获并处理CTRL+C的信号,即SIGINT(终端中断信号)。
【讨论】:
让我总结一下我认为您的问题是:每当您按 ctrl+c 关闭客户端时,服务器就会退出。并且您希望以服务器不会像上面那样崩溃的方式处理此行为。如果这是真的,请继续阅读,我想我可以对实际问题有所了解,这与使用(或不使用)正确的信号句柄没有太大关系。
当您使用 ctrl+c 关闭客户端时,操作系统将停止客户端进程并关闭它打开的所有套接字。作为其中的一部分,将向服务器发送一个 FIN。
请检查您的代码。我相信你会以这样一种方式编写代码,即它在来自相关客户端的套接字的 read() 调用中被阻塞。现在,当上面发送的 FIN 到达服务器端套接字时,这个读取将返回值 0。
如果您的代码不检查这种情况并尝试将某些内容写回客户端,最终(我跳过中间发生的几个步骤)它将收到一个 SIGPIPE。这将导致您的服务器崩溃。
如果上述情况属实,您有两种出路: 1. 检查 read() 返回 0 并优雅地继续。 2. 为 SIGPIPE 安装一个信号处理程序。
我更喜欢第一种方法,顺便说一句。
【讨论】:
为了关闭套接字连接并正确终止 ctrl-c 上的客户端程序,您可能需要为 SIGINT 提供适当的信号处理程序。这是使用signal() 或者最好是sigaction() 函数来完成的。
这个问题及其答案可能很有趣:How should I close a socket in a signal handler?
在您的服务器程序上,您应该通过检查函数的返回值来检查每个涉及套接字的函数的错误,例如accept() 或recv()/read()。如果函数的返回值指示错误(通常为 -1),请查看 errno。 errno 的值应该提供一些关于错误性质的指示,并允许正确处理错误情况。这应该可以帮助您更好地处理客户端应用程序意外终止时连接丢失的情况。
【讨论】: