1、阻塞模式與非阻塞模式下recv的返回值各代表什麼意思?有沒有區別?(就我目前了解阻塞與非阻塞recv返回值沒有區分,都是 <0:出錯,=0:連線關閉,>0接收到資料大小,特別:返回值 <0時並且(errno == eintr || errno == ewouldblock || errno == eagain)的情況下認為連線是正常的,繼續接收。只是阻塞模式下recv會阻塞著接收資料,非阻塞模式下如果沒有資料會返回,不會阻塞著讀,因此需要 迴圈讀取
2、阻塞模式與非阻塞模式下write的返回值各代表什麼意思?有沒有區別?
阻塞與非阻塞write返回值沒有區分,都是 <0:出錯,=0:連線關閉,>0傳送資料大小,特別:返回值 <0時並且(errno == eintr || errno == ewouldblock || errno == eagain)的情況下認為連線是正常的,繼續傳送。只是阻塞模式下write會阻塞著傳送資料,非阻塞模式下如果暫時無法傳送資料會返回,不會阻塞著 write,因此需要迴圈傳送
3、阻塞模式下read返回值 < 0 && errno != eintr && errno != ewouldblock && errno != eagain時,連線異常,需要關閉,read返回值 < 0 && (errno == eintr || errno == ewouldblock || errno == eagain)時表示沒有資料,需要繼續接收,如果返回值大於0表示接送到資料。
非阻塞模式下read返回值 < 0表示沒有資料,= 0表示連線斷開,> 0表示接收到資料。
這2種模式下的返回值是不是這麼理解,有沒有跟詳細的理解或跟準確的說明?
4、阻塞模式與非阻塞模式下是否send返回值 < 0 && (errno == eintr || errno == ewouldblock || errno == eagain)表示暫時傳送失敗,需要重試,如果send返回值 <= 0, && errno != eintr && errno != ewouldblock && errno != eagain時,連線異常,需要關閉,如果send返回值 > 0則表示傳送了資料?send的返回值是否這麼理解,阻塞模式與非阻塞模式下send返回值=0是否都是傳送失敗,還是那個模式下表示暫時不可傳送,需要 重發?
send函式
int send( socket s, const char far *buf, int len, int flags );
不論是客戶端還是伺服器端應用程式都用send函式來向tcp連線的另一端傳送資料。
客戶端程式一般用send函式向伺服器傳送請求,而伺服器則通常用send函式來向客戶程式傳送應答。
該函式的:
第乙個引數指定傳送端套接字描述符;
第二個引數指明乙個存放應用程式要傳送資料的緩衝區;
第三個引數指明實際要傳送的資料的位元組數;
第四個引數一般置0。
這裡只描述同步socket的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)
注意:在unix系統下,如果send在等待協議傳送資料時網路斷開的話,呼叫send的程序會接收到乙個sigpipe訊號,程序對該訊號的預設處理是程序終止。
send函式的返回值有三類:
(1)返回值=0:
(2)返回值<0:傳送失敗,錯誤原因存於全域性變數errno中
(3)返回值》0:表示傳送的位元組數(實際上是拷貝到傳送緩衝中的位元組數)
錯誤**:
ebadf 引數s 非合法的socket處理**。
efault 引數中有一指標指向無法訪問的記憶體空間
enotsock 引數s為一檔案描述詞,非socket。
eintr 被訊號所中斷。
eagain 此操作會令程序阻斷,但引數s的socket為不可阻斷。
enobufs 系統的緩衝記憶體不足
enomem 核心記憶體不足
einval 傳給系統呼叫的引數不正確。
recv函式
int recv( socket s, char far *buf, int len, int flags );
不論是客戶端還是伺服器端應用程式都用recv函式從tcp連線的另一端接收資料。
該函式的:
第乙個引數指定接收端套接字描述符;
第二個引數指明乙個緩衝區,該緩衝區用來存放recv函式接收到的資料;
第三個引數指明buf的長度;
第四個引數一般置0。
這裡只描述同步socket的recv函式的執行流程。當應用程式呼叫recv函式時,recv先等待s的傳送緩衝 中的資料被協議傳送完畢,如果協議在傳送s的傳送緩衝中的資料時出現網路錯誤,那麼recv函式返回socket_error,如果s的傳送緩衝中沒有數 據或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,只到 協議把資料接收完畢。當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以 在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。recv函式僅僅是copy資料,真正的接收資料是協議來完成的),recv函式返回其實際copy的位元組數。如果recv在copy時出錯,那麼它返回socket_error;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。
注意:在unix系統下,如果recv函式在等待協議接收資料時網路斷開了,那麼呼叫recv的程序會接收到乙個sigpipe訊號,程序對該訊號的預設處理是程序終止。
預設情況下socket是阻塞的。
阻塞與非阻塞recv返回值沒有區別,都是:
<0 出錯
=0 對方呼叫了close api來關閉連線
0 接收到的資料大小,特別地:返回值<0時並且(errno == eintr || errno == ewouldblock || errno == eagain)的情況下認為連線是正常的,繼續接收。
只是阻塞模式下recv會一直阻塞直到接收到資料,非阻塞模式下如果沒有資料就會返回,不會阻塞著讀,因此需要迴圈讀取)。
返回說明:
(1)成功執行時,返回接收到的位元組數。
(2)若另一端已關閉連線則返回0,這種關閉是對方主動且正常的關閉
(3)失敗返回-1,errno被設為以下的某個值
eagain:套接字已標記為非阻塞,而接收操作被阻塞或者接收超時
ebadf:sock不是有效的描述詞
econnrefuse:遠端主機阻絕網路連線
efault:記憶體空間訪問出錯
eintr:操作被訊號中斷
einval:引數無效
enomem:記憶體不足
enotconn:與面向連線關聯的套接字尚未被連線上
enotsock:sock索引的不是套接字
關於udp套接字
setsockopt so reuseaddr 同一終端先後兩次執行udp server,該選項無影響。兩個 或多個 終端同時執行udp server,配置該選項時,僅第乙個終端執行成功 不配置時,所有終端均可成功執行udp server。udp客戶端呼叫connect 實現 不發起三次握手 僅將服...
監聽套接字 連線套接字
摘要 對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。accept函式等待並接受客戶請求 inclu...
監聽套接字 連線套接字的區別
摘要 對於伺服器程式設計中最重要的一步等待並接受客戶的連線,那麼這一步在程式設計中如何完成,accept函式就是完成這一步的。它從核心中取出已經建立的客戶連線,然後把這個已經建立的連線返回給使用者程式,此時使用者程式就可以與自己的客戶進行點到點的通訊了。accept函式等待並接受客戶請求 inclu...