recv 和 send 阻塞和非阻塞的区别
目錄
答案
深入說(shuō)明
在 epoll 中的應(yīng)用
總結(jié)
拓展
答案
深入說(shuō)明
// 將內(nèi)核接收緩沖區(qū)中的數(shù)據(jù) copy 到應(yīng)用層中用戶的 buffer 中。 int recv(int sockfd, void *buf, size_t len, int flag); // 將應(yīng)用層中用戶的 buffer 中的數(shù)據(jù) copy 到內(nèi)核發(fā)送緩沖區(qū)中。 int send(int sockfd, void *buf, size_t len, int flag);1、recv?
阻塞模式下,如果內(nèi)核的接收緩沖區(qū)中沒有數(shù)據(jù)時(shí),該函數(shù)就會(huì)阻塞。
非阻塞模式下,如果內(nèi)核的接收緩沖區(qū)中沒有數(shù)據(jù)時(shí),該函數(shù)就會(huì)返回。
2、send
阻塞模式下,如果發(fā)送緩沖區(qū)剩余的空間小于要發(fā)送的數(shù)據(jù)的大小,那么該函數(shù)會(huì)阻塞。
非阻塞模式下,如果發(fā)送緩沖區(qū)剩余的空間大于要發(fā)送的數(shù)據(jù)的大小,那么該函數(shù)會(huì)返回。
在 epoll 中的應(yīng)用
1、水平觸發(fā)模式(LT)
在該模式下,recv 和 send 為阻塞和非阻塞,結(jié)果是一樣的。
舉 recv 栗子來(lái)說(shuō),因?yàn)樵谠撚|發(fā)模式下,只要內(nèi)核的接收緩沖區(qū)中有數(shù)據(jù),epoll_wait()?函數(shù)都會(huì)返回,這就導(dǎo)致了雖然 recv 是阻塞模式的,但是每次調(diào)用時(shí),內(nèi)核緩沖區(qū)都是有數(shù)據(jù)的,所以不會(huì)導(dǎo)致 recv 阻塞。當(dāng)然了,當(dāng) recv 時(shí)是非阻塞的,就更不會(huì)造成阻塞情況了。同理,對(duì)于 send 也是一樣的。
2、邊沿觸發(fā)模式(LT)
在該模式下,recv 和 send 需要為非阻塞模式,不然就會(huì)有問(wèn)題。
還是舉 recv 栗子來(lái)說(shuō),因?yàn)樵谠撃J较?#xff0c;內(nèi)核的接收緩沖區(qū)來(lái)數(shù)據(jù)了,那么 epoll_wait() 函數(shù)就會(huì)返回,但是僅僅返回一次,它可不管你是否在該次中是否完全取走了內(nèi)核接收緩沖區(qū)中的數(shù)據(jù)。
在上述的前提下,recv 需要一個(gè) while (true) 循環(huán),保證將緩沖區(qū)中的數(shù)據(jù)取空。這就產(chǎn)生了一個(gè)問(wèn)題,因?yàn)榧偃?recv 是阻塞的,那么當(dāng)內(nèi)核緩沖區(qū)中沒有數(shù)據(jù)時(shí),該函數(shù)就會(huì)阻塞,這是致命的,所以 recv 必須是非阻塞的。
同理,對(duì)于 send 也是一樣的。理想情況時(shí),終于有機(jī)會(huì)向?qū)Χ税l(fā)送數(shù)據(jù)了,一定要將想發(fā)的數(shù)據(jù)發(fā)盡。這就有問(wèn)題了,如果是阻塞的,如果發(fā)到一半,發(fā)送緩沖區(qū)滿了,那么該函數(shù)就阻塞了,實(shí)際上要避免這種情況,所以要將該 send 設(shè)置為非阻塞的。
總結(jié)
在水平觸發(fā)模式下,recv 和 send 阻塞和非阻塞模式均可。
在邊沿觸發(fā)模式下,recv 和 send 必須為非阻塞模式。
拓展
1、將socket設(shè)置為非阻塞模式的方法。(socket設(shè)置為非阻塞的,recv 和 send 要設(shè)置為非阻塞的)
int flags = fcntl(sockfd, F_GETFL, 0); //獲取文件的flags值。fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); //設(shè)置成非阻塞模式; int n = recv(fd, pbuff, kBuffLen, MSG_DONTWAIT);?2、將socket設(shè)置為阻塞模式的方法。
int flags = fcntl(sockfd, F_GETFL, 0); //獲取文件的flags值。fcntl(sockfd, F_SETFL, flags | ~O_NONBLOCK); //設(shè)置成阻塞模式; int n = recv(fd, pbuff, kBuffLen, 0); // flag = 0,默認(rèn)是阻塞的。?
(SAW:Game Over!)
總結(jié)
以上是生活随笔為你收集整理的recv 和 send 阻塞和非阻塞的区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TCP/IP / UDP 头
- 下一篇: C/Cpp / STL / vector