C++ Socket程式設計(二) send與recv 緩衝區與阻塞
socket緩衝區
每一個socket在被建立之後,系統都會給它分配兩個緩衝區,即輸入緩衝區和輸出緩衝區。
send函式並不是直接將資料傳輸到網路中,而是負責將資料寫入輸出緩衝區,資料從輸出緩衝區傳送到目標主機是由TCP協議完成的。資料寫入到輸出緩衝區之後,send函式就可以返回了,資料是否傳送出去,是否傳送成功,何時到達目標主機,都不由它負責了,而是由協議負責。
recv函式也是一樣的,它並不是直接從網路中獲取資料,而是從輸入緩衝區中讀取資料。
輸入輸出緩衝區,系統會為每個socket都單獨分配,並且是在socket建立的時候自動生成的。一般來說,預設的輸入輸出緩衝區大小為8K。套接字關閉的時候,輸出緩衝區的資料不會丟失,會由協議傳送到另一方;而輸入緩衝區的資料則會丟失。
socket資料傳送與接收問題
資料的傳送和接收是獨立的,並不是傳送方執行一次send,接收方就執行以此recv。recv函式不管傳送幾次,都會從輸入緩衝區儘可能多的獲取資料。如果傳送方傳送了多次資訊,接收方沒來得及進行recv,則資料堆積在輸入緩衝區中,取資料的時候會都取出來。換句話說,recv並不能判斷資料包的結束位置。
send函式:
在資料進行傳送的時候,需要先檢查輸出緩衝區的可用空間大小,如果可用空間大小小於要傳送的資料長度,則send會被阻塞,直到緩衝區中的資料被髮送到目標主機,有了足夠的空間之後,send函式才會將資料寫入輸出緩衝區。
TCP協議正在將資料傳送到網路上的時候,輸出緩衝區會被鎖定(生產者消費者問題),不允許寫入,send函式會被阻塞,直到資料傳送完,輸出緩衝區解鎖,此時send才能將資料寫入到輸出緩衝區。
要寫入的資料大於輸出緩衝區的最大長度的時候,要分多次寫入,直到所有資料都被寫到緩衝區之後,send函式才會返回。
recv函式:
函式先檢查輸入緩衝區,如果輸入緩衝區中有資料,讀取出緩衝區中的資料,否則的話,recv函式會被阻塞,等待網路上傳來資料。如果讀取的資料長度小於輸出緩衝區中的資料長度,沒法一次性將所有資料讀出來,需要多次執行recv函式,才能將資料讀取完畢。