socket api中send()和recv()函数工作原理与要点
send()和recv()函數(shù)是網(wǎng)絡(luò)編程中經(jīng)常使用到的函數(shù),下面詳細(xì)的比較兩者的不同之處
send函數(shù)工作原理:
??send函數(shù)只負(fù)責(zé)將數(shù)據(jù)提交給協(xié)議層。?當(dāng)調(diào)用該函數(shù)時(shí),send先比較待發(fā)送數(shù)據(jù)的長度len和套接字s的發(fā)送緩沖區(qū)的長度,如果len大于s的發(fā)送緩沖區(qū)的長度,該函數(shù)返回SOCKET_ERROR;?如果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;?如果len大于剩余空間大小,send就一直等待協(xié)議把s的發(fā)送緩沖中的數(shù)據(jù)發(fā)送完,如果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ù)成功,就返回實(shí)際copy的字節(jié)數(shù),如果send在copy數(shù)據(jù)時(shí)出現(xiàn)錯(cuò)誤,那么send就返回SOCKET_ERROR;?如果send在等待協(xié)議傳送數(shù)據(jù)時(shí)網(wǎng)絡(luò)斷開的話,那么send函數(shù)也返回SOCKET_ERROR。
? ?要注意send函數(shù)把buf中的數(shù)據(jù)成功copy到s的發(fā)送緩沖的剩余空間里后它就返回了,但是此時(shí)這些數(shù)據(jù)并不一定馬上被傳到連接的另一端。?如果協(xié)議在后續(xù)的傳送過程中出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤的話,那么下一個(gè)Socket函數(shù)就會(huì)返回SOCKET_ERROR。(每一個(gè)除send外的Socket函數(shù)在執(zhí)行的最開始總要先等待套接字的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢才能繼續(xù),如果在等待時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,那么該Socket函數(shù)就返回SOCKET_ERROR)???
recv函數(shù)工作原理:
???recv先檢查套接字s的接收緩沖區(qū),如果s接收緩沖區(qū)中沒有數(shù)據(jù)或者協(xié)議正在接收數(shù)據(jù),那么recv就一直等待,直到協(xié)議把數(shù)據(jù)接收完畢。當(dāng)協(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ù)返回其實(shí)際copy的字節(jié)數(shù)。如果recv在copy時(shí)出錯(cuò),那么它返回SOCKET_ERROR;如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)中斷了,那么它返回0?。? 對(duì)方優(yōu)雅的關(guān)閉socket并不影響本地recv的正常接收數(shù)據(jù);如果協(xié)議緩沖區(qū)內(nèi)沒有數(shù)據(jù),recv返回0,指示對(duì)方關(guān)閉;如果協(xié)議緩沖區(qū)有數(shù)據(jù),則返回對(duì)應(yīng)數(shù)據(jù)(可能需要多次recv),在最后一次recv時(shí),返回0,指示對(duì)方關(guān)閉。
要點(diǎn):
在進(jìn)行TCP協(xié)議傳輸?shù)臅r(shí)候,要注意數(shù)據(jù)流傳輸?shù)奶攸c(diǎn),recv和send不一定是一一對(duì)應(yīng)的(一般情況下是一一對(duì)應(yīng)),也就是說并不是send一次,就一定recv一次就接收完,有可能send一次,recv多次才接收完,也可能send多次,一次recv就接收完了。TCP協(xié)議會(huì)保證數(shù)據(jù)的有序完整的傳輸,但是如何去正確完整的處理每一條信息,是程序員的事情。
例如:服務(wù)器在循環(huán)recv,recv的緩沖區(qū)大小為100byte,客戶端在循環(huán)send,每次send 6byte數(shù)據(jù),則recv每次收到的數(shù)據(jù)可能為6byte,12byte,18byte,這是隨機(jī)的,編程的時(shí)候注意正確的處理。
???????? 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的socket api中send()和recv()函数工作原理与要点的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis之整数集合intset
- 下一篇: 敏感词过滤算法的实现