1. 程式人生 > >socket api中send()和recv()函式工作原理與要點

socket api中send()和recv()函式工作原理與要點

send()和recv()函式是網路程式設計中經常使用到的函式,下面詳細的比較兩者的不同之處

send函式工作原理

 send函式只負責將資料提交給協議層。 當呼叫該函式時,send先比較待發送資料的長度len和套接字s的傳送緩衝區的長度,如果len大於s的傳送緩衝區的長度,該函式返回SOCKET_ERROR; 如果len小於或者等於s的傳送緩衝區的長度,那麼send先檢查協議是否正在傳送s的傳送緩衝中的資料; 如果是就等待協議把資料傳送完,如果協議還沒有開始傳送s的傳送緩衝中的資料或者s的傳送緩衝中沒有資料,那麼send就比較s的傳送緩衝區的剩餘空間和len; 如果len大於剩餘空間大小,send就一直等待協議把s的傳送緩衝中的資料傳送完,如果len小於剩餘空間大小,send就僅僅把buf中的資料copy到剩餘空間裡(注意並不是send把s的傳送緩衝中的資料傳到連線的另一端的,而是協議傳的,send僅僅是把buf中的資料copy到s的傳送緩衝區的剩餘空間裡
)。 如果send函式copy資料成功,就返回實際copy的位元組數,如果send在copy資料時出現錯誤,那麼send就返回SOCKET_ERROR; 如果send在等待協議傳送資料時網路斷開的話,那麼send函式也返回SOCKET_ERROR。

   要注意send函式把buf中的資料成功copy到s的傳送緩衝的剩餘空間裡後它就返回了,但是此時這些資料並不一定馬上被傳到連線的另一端。 如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個Socket函式就會返回SOCKET_ERROR。(每一個除send外的Socket函式在執行的最開始總要先等待套接字的傳送緩衝中的資料被協議傳送完畢才能繼續,如果在等待時出現網路錯誤,那麼該Socket函式就返回SOCKET_ERROR

) 

recv函式工作原理:

recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,直到協議把資料接收完畢。當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。recv函式僅僅是copy資料,真正的接收資料是協議來完成的),recv函式返回其實際copy的位元組數。如果recv在copy時出錯,那麼它返回SOCKET_ERROR;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0 。

  對方優雅的關閉socket並不影響本地recv的正常接收資料;如果協議緩衝區內沒有資料,recv返回0,指示對方關閉;如果協議緩衝區有資料,則返回對應資料(可能需要多次recv),在最後一次recv時,返回0,指示對方關閉。

要點:

在進行TCP協議傳輸的時候,要注意資料流傳輸的特點,recv和send不一定是一一對應的(一般情況下是一一對應),也就是說並不是send一次,就一定recv一次就接收完,有可能send一次,recv多次才接收完,也可能send多次,一次recv就接收完了。TCP協議會保證資料的有序完整的傳輸,但是如何去正確完整的處理每一條資訊,是程式設計師的事情。

例如:伺服器在迴圈recv,recv的緩衝區大小為100byte,客戶端在迴圈send,每次send 6byte資料,則recv每次收到的資料可能為6byte,12byte,18byte,這是隨機的,程式設計的時候注意正確的處理。