C++程式設計-socket程式設計中為何要使用迴圈來呼叫阻塞式recv
你是否奇怪阻塞式接收recv這樣的函式為什麼要用一個for迴圈才能收全所有的內容?至少其中一種可能性是因為UNIX的訊號處理機制。
在我的程式設計理念中,UNIX下的訊號是一個徒增麻煩的東西,這也許是非控制檯的Windows程式中沒有訊號的原因。
試想,如果你寫了一個程式,無論是一個7*24的,還是一次性執行的,你通常期望它做完一段完整的工作後才被停下來,而不是在接收到一個也許你並不想要的訊號直接就退出來。除非你在寫一個初級的試驗用的小程式,比如在寫一個沒有辦法優雅關閉的死迴圈,不打算在正式的生產系統上使用,不需要完整的處理一個事務後結束,你可以慵懶的使用一下訊號,其他情況下,最好把它遮蔽掉。
當然,你可以在接收到訊號後設置退出標誌,然後優雅的退出,然而有時候你並不能確信這個訊號是你有意發出,因此最好的辦法是你遮蔽掉所有的訊號,在需要關閉時,使用自己的命令去關閉程式。
訊號充當的是軟體中斷,向程式指示非同步事件的發生。要處理訊號,需要將訊號處理器與一個特定的訊號型別關聯起來。在訊號處理器返回後,程式會在主上下文中,從收到訊號之前的地方繼續執行。
遮蔽掉一個訊號,可以在捕捉到該訊號後呼叫一個空函式,也可以在signal函式中設定SIG_IGN來遮蔽訊號。然而僅僅遮蔽了它是不夠的,因為特定的阻塞式系統呼叫(如recv、read、write、ioctl等在訊號發生時會退出阻塞。一旦退出阻塞,會把errorno設定為EINTR。
因此,正常情況下我們需要對阻塞式的recv進行迴圈呼叫。
至於停止程式,我們可以自己寫一個管理程式,與我們的程式間進行程序間通訊,這樣我們就可以優雅的停止我們的程式了。