recv是阻塞還是非阻塞的?
socket分為阻塞和非阻塞兩種,可以通過setsockopt,或者更簡單的setblocking, settimeout設置。
阻塞式的socket的recv服從這樣的規則:當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,阻塞直到緩沖區中有數據。
非阻塞式的socket的recv服從的規則則是:當緩沖區內有數據時,立即返回所有的數據;當緩沖區內無數據時,產生EAGAIN的錯誤并返回(在Python中會拋出一個異常)。
兩種情況都不會返回空字符串,返回空數據的結果是對方關閉了連接之后才會出現的。由于TCP的socket是一個流,因此是不存在“讀完了對方發送來的數據”這件事的。
你必須要每次讀到數據之后,根據數據本身來判斷當前需要等待的數據是否已經全部收到,來判斷是否進行下一個recv。
可以看一下hiredis庫的接口設計,hiredis中的Reader有兩個接口,分別是feed和gets,feed每次送入一部分數據,不需要保證是正確分片的;gets則返回已經得到的完整的結果,如果返回False,表示已經沒有新的結果。基本上所有的TCP的socket編程都是遵循這樣的方法:讀入新數據;判斷有沒有完整的新消息;處理新消息,或者等待更多數據。