首先什麼是阻塞,什麼是非阻塞呢?
通俗的說,阻塞就是事情沒幹完,但是現在暫時無法幹,還得在那兒等着
非阻塞就是事情沒幹完,現在暫時沒法幹,我先離開一會兒,待會兒回來再幹。
拿recv和send函數來說,send發送一定byte的數據,其實是把數據拷貝到TCP/IP協議棧中的輸出mbuf(http://blog.csdn.net/shinichr/article/details/23044999)中,它執行成功不是指已經成功的把數據發給了對方。
這時候如果輸出mbuf沒有足夠的空間保存數據呢?對於阻塞模式下,send將不返回知道mbuf有足夠的空間來保存數據。而非阻塞模式會立即返回一個緩存區已滿的提醒,這時候需要我們去處理。
對於recv來說,道理和send類似的。
那麼socket的阻塞函數有哪些呢?
accept,connect,recv(recvfrom),send(sendto),closesocket,select(poll或epoll)
accept在阻塞模式下,沒有新連接時,線程會進入睡眠狀態;非阻塞模式下,沒有新連接時,立即返回WOULDBLOCK錯誤。
connect在阻塞模式下,僅TCP連接建立成功或出錯時才返回,分幾種具體的情況,這裏不再敘述;非阻塞模式下,該函數會立即
返回INPROCESS錯誤(可以用select檢測該連接是否建立成功)
select/poll/epoll並不是真正意義上的阻塞,它們的阻塞是由於它們最後一個timeout參數決定的,timeout大於0時,它們會一
直等待直到超時才退出(相等於阻塞),而timeout=-1即永遠等待。
設置socket阻塞模式方法也很簡單:
linux:
fcntl(socket, F_SETFL, flags | O_NONBLOCK);
read/recv函數的最後一個參數也可以設置阻塞或非阻塞方式
windows:
ioctlsocket,WSAAsyncselect()和WSAEventselect()
read/recv函數的最後一個參數也可以設置阻塞或非阻塞方式