C++编程-socket编程中为何要使用循环来调用阻塞式recv

来源:互联网 发布:淘宝查号软件 编辑:程序博客网 时间:2024/05/16 01:19

        你是否奇怪阻塞式接收recv这样的函数为什么要用一个for循环才能收全所有的内容?至少其中一种可能性是因为UNIX的信号处理机制。
        在我的编程理念中,UNIX下的信号是一个徒增麻烦的东西,这也许是非控制台的Windows程序中没有信号的原因。
        试想,如果你写了一个程序,无论是一个7*24的,还是一次性运行的,你通常期望它做完一段完整的工作后才被停下来,而不是在接收到一个也许你并不想要的信号直接就退出来。除非你在写一个初级的试验用的小程序,比如在写一个没有办法优雅关闭的死循环,不打算在正式的生产系统上使用,不需要完整的处理一个事务后结束,你可以慵懒的使用一下信号,其他情况下,最好把它屏蔽掉。
        当然,你可以在接收到信号后设置退出标志,然后优雅的退出,然而有时候你并不能确信这个信号是你有意发出,因此最好的办法是你屏蔽掉所有的信号,在需要关闭时,使用自己的命令去关闭程序。
        信号充当的是软件中断,向程序指示异步事件的发生。要处理信号,需要将信号处理器与一个特定的信号类型关联起来。在信号处理器返回后,程序会在主上下文中,从收到信号之前的地方继续执行。
        屏蔽掉一个信号,可以在捕捉到该信号后调用一个空函数,也可以在signal函数中设置SIG_IGN来屏蔽信号。然而仅仅屏蔽了它是不够的,因为特定的阻塞式系统调用(如recv、read、write、ioctl等在信号发生时会退出阻塞。一旦退出阻塞,会把errorno设置为EINTR。
        因此,正常情况下我们需要对阻塞式的recv进行循环调用。
        至于停止程序,我们可以自己写一个管理程序,与我们的程序间进行进程间通信,这样我们就可以优雅的停止我们的程序了。