1.send 函數(shù)
int?send(?SOCKET?s, const?char?FAR?*buf,
int?len, int?flags?);
不論是客戶還是服務器應用程序都用send函數(shù)來向TCP連接的另一端發(fā)送數(shù)據(jù)??蛻舫绦蛞话阌胹end函數(shù)向服務器發(fā)送請求,而服務器則通常用send函數(shù)來向客戶程序發(fā)送應答。
該函數(shù)的第一個參數(shù)指定發(fā)送端套接字描述符;
第二個參數(shù)指明一個存放應用程序要發(fā)送數(shù)據(jù)的緩沖區(qū);
第三個參數(shù)指明實際要發(fā)送的數(shù)據(jù)的字節(jié)數(shù);
第四個參數(shù)一般置0。
這里只描述同步Socket的send函數(shù)的執(zhí)行流程。當調(diào)用該函數(shù)時,
(1)send先比較待發(fā)送數(shù)據(jù)的長度len和套接字s的發(fā)送緩沖的長度,?如果len大于s的發(fā)送緩沖區(qū)的長度,該函數(shù)返回SOCKET_ERROR;
(2)如果len小于或者等于s的發(fā)送緩沖區(qū)的長度,那么send先檢查協(xié)議是否正在發(fā)送s的發(fā)送緩沖中的數(shù)據(jù),如果是就等待協(xié)議把數(shù)據(jù)發(fā)送完,如果協(xié)議
還沒有開始發(fā)送s的發(fā)送緩沖中的數(shù)據(jù)或者s的發(fā)送緩沖中沒有數(shù)據(jù),那么send就比較s的發(fā)送緩沖區(qū)的剩余空間和len
(3)如果len大于剩余空間大小,send就一直等待協(xié)議把s的發(fā)送緩沖中的數(shù)據(jù)發(fā)送完
(4)如果len小于剩余?空間大小,send就僅僅把buf中的數(shù)據(jù)copy到剩余空間里(注意并不是send把s的發(fā)送緩沖中的數(shù)據(jù)傳到連接的另一端的,而是協(xié)議傳的,send僅僅是把buf中的數(shù)據(jù)copy到s的發(fā)送緩沖區(qū)的剩余空間里)。
如果send函數(shù)copy數(shù)據(jù)成功,就返回實際copy的字節(jié)數(shù),如果send在copy數(shù)據(jù)時出現(xiàn)錯誤,那么send就返回SOCKET_ERROR;如果send在等待協(xié)議傳送數(shù)據(jù)時網(wǎng)絡斷開的話,那么send函數(shù)也返回SOCKET_ERROR。
要注意send函數(shù)把buf中的數(shù)據(jù)成功copy到s的發(fā)送緩沖的剩余空間里后它就返回了,但是此時這些數(shù)據(jù)并不一定馬上被傳到連接的另一端。如
果協(xié)議在后續(xù)的傳送過程中出現(xiàn)網(wǎng)絡錯誤的話,那么下一個Socket函數(shù)就會返回SOCKET_ERROR。(每一個除send外的Socket函數(shù)在
執(zhí)?行的最開始總要先等待套接字的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢才能繼續(xù),如果在等待時出現(xiàn)網(wǎng)絡錯誤,那么該Socket函數(shù)就返
回?SOCKET_ERROR)
注意:在Unix系統(tǒng)下,如果send在等待協(xié)議傳送數(shù)據(jù)時網(wǎng)絡斷開的話,調(diào)用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。
通過測試發(fā)現(xiàn),異步socket的send函數(shù)在網(wǎng)絡剛剛斷開時還能發(fā)送返回相應的字節(jié)數(shù),同時使用select檢測也是可寫的,但是過幾秒鐘之后,再send就會出錯了,返回-1。select也不能檢測出可寫了。
2. recv函數(shù)
int?recv(?SOCKET?s, char?FAR?*buf, int?len, int?flags);
不論是客戶還是服務器應用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù)。該函數(shù)的第一個參數(shù)指定接收端套接字描述符;
第二個參數(shù)指明一個緩沖區(qū),該緩沖區(qū)用來存放recv函數(shù)接收到的數(shù)據(jù);
第三個參數(shù)指明buf的長度;
第四個參數(shù)一般置0。
這里只描述同步Socket的recv函數(shù)的執(zhí)行流程。當應用程序調(diào)用recv函數(shù)時,
(1)recv先等待s的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢,如果協(xié)議在傳送s的發(fā)送緩沖中的數(shù)據(jù)時出現(xiàn)網(wǎng)絡錯誤,那么recv函數(shù)返回SOCKET_ERROR,
(2)如果s的發(fā)送緩沖中沒有數(shù)據(jù)或者數(shù)據(jù)被協(xié)議成功發(fā)送完畢后,recv先檢查套接字s的接收緩沖區(qū),如果s接收緩沖區(qū)中沒有數(shù)據(jù)或者協(xié)議正在接收數(shù)
據(jù),那么recv就一直等待,直到協(xié)議把數(shù)據(jù)接收完畢。當協(xié)議把數(shù)據(jù)接收完畢,recv函數(shù)就把s的接收緩沖中的數(shù)據(jù)copy到buf中(注意協(xié)議接收到的數(shù)據(jù)可能大于buf的長度,所以?在這種情況下要調(diào)用幾次recv函數(shù)才能把s的接收緩沖中的數(shù)據(jù)copy完。recv函數(shù)僅僅是copy數(shù)據(jù),真正的接收數(shù)據(jù)是協(xié)議來完成的),
recv函數(shù)返回其實際copy的字節(jié)數(shù)。如果recv在copy時出錯,那么它返回SOCKET_ERROR;如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時網(wǎng)絡中斷了,那么它返回0。
注意:在Unix系統(tǒng)下,如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時網(wǎng)絡斷開了,那么調(diào)用recv的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。