Socket調用方式(同步,異步,阻塞,非阻塞)

同步:編程

我調用一個功能,該功能沒有結束前,我死等結果。promise

異步:異步

當一個異步過程調用發出後,調用者不能馬上獲得結果。該功能在完成後,經過狀態、通知和回調來通知調用者。socket

同步和非同步關注的是調用者是否等待等待調用結果。分佈式

舉個通俗的例子:
你打電話問書店老闆有沒有《分佈式系統》這本書,若是是同步通訊機制,書店老闆會說,你稍等,」我查一下",而後開始查啊查,等查好了(多是5秒,也多是一天)告訴你結果(返回結果)。
而異步通訊機制,書店老闆直接告訴你我查一下啊,查好了打電話給你,而後直接掛電話了(不返回結果)。而後查好了,他會主動打電話給你。在這裏老闆經過「回電」這種方式來回調。異步編程

 

阻塞函數

調用我(函數),我(函數)沒有接收完數據或者沒有獲得結果以前,我不會返回。this

非阻塞spa

調用我(函數),我(函數)當即返回通知調用者線程

以最經常使用的send和recv兩個函數爲例
好比你調用send函數發送必定的Byte,在系統內部send作的工做其實只是把數據傳輸(Copy)到TCP/IP協議棧的輸出緩衝區,它執行成功並不表明數據已經成功的發送出去了,若是TCP/IP協議棧沒有足夠的可用緩衝區來保存你Copy過來的數據的話...這時候就體現出阻塞和非阻塞的不一樣之處了:對於阻塞模式的socket send函數將不返回直到系統緩衝區有足夠的空間把你要發送的數據Copy過去之後才返回,而對於非阻塞的socket來講send會當即返回WSAEWOULDDBLOCK告訴調用者說:"發送操做被阻塞了!!!你想辦法處理吧..." 
對於recv函數,一樣道理,對於阻塞模式的socket來講若是TCP/IP協議棧的接收緩衝區沒有通知一個結果給它它就一直不返回:耗費着系統資源....對於非阻塞模式的socket該函數會立刻返回,而後告訴你:WSAEWOULDDBLOCK---"如今沒有數據,回頭再來看看"

阻塞I/O模型:

非阻塞I/O模型:

阻塞和非阻塞關注的是調用者在等待調用結果時的狀態。

仍是上面的例子,
你打電話問書店老闆有沒有《分佈式系統》這本書,你若是是阻塞式調用,你會一直把本身「掛起」,直到獲得這本書有沒有的結果,若是是非阻塞式調用,你無論老闆有沒有告訴你,你本身先一邊去玩了, 固然你也要偶爾過幾分鐘check一下老闆有沒有返回結果。

 

同步異步與阻塞非阻塞的關係:

  • 在處理 IO 的時候,阻塞和非阻塞都是同步 IO。socket接收數據的recv函數,若是沒有數據的狀況下調用該函數,則當前線程就會被掛起,直到有數據爲止(同步&阻塞);CSocket中調用Receive函數,若是緩衝區中沒有數據,這個函數就會一直等待,直到有數據才返回,而此時,當前線程還會繼續處理各類各樣的消息(同步&非阻塞)。
  • 只有使用了特殊的 API 纔是異步 IO。

 

異步調用的方式:

Javascript語言的執行環境是"單線程"(single thread)。所謂"單線程",就是指一次只能完成一件任務。若是有多個任務,就必須排隊。解決方法:實現異步。
例1:回調函數。A先告訴B去點亮,而後本身點亮。B的點亮操做並不會阻塞A。
複製代碼
function lightUp(A, callback){ 

 callback(); 

 A.lightUp(); 

} 

function callback(){

 B.lightUp(); 

}
複製代碼
***同步調用時這樣的***
複製代碼
var temp = false; 

while(!temp){
  temp = wait(A.lightUp());
}

B.lightUp();
複製代碼

 

例2:事件監聽。
複製代碼
function AlightUp(){ 

 this.trigger('done'); 

 this.do(); 

} 

function BlightUp(){ 

 this.do(); 

}
AlightUp.on('done',BlightUp);
複製代碼

 

例3:發佈/訂閱。
複製代碼
jQuery.subscribe("done", f2); 
function f1(){
  setTimeout(function () {
    // f1的任務代碼
    jQuery.publish("done");
  }, 1000);
}  
複製代碼
f2完成執行後,也能夠取消訂閱(unsubscribe)。
jQuery.unsubscribe("done", f2); 
這種方法的性質與"事件監聽"相似,可是明顯優於後者。由於咱們能夠經過查看"消息中心",瞭解存在多少信號、每一個信號有多少訂閱者,從而監控程序的運行。
 
例4:Promises
Promises對象是CommonJS工做組提出的一種規範,目的是爲異步編程提供統一接口。
簡單說,它的思想是,每個異步任務返回一個Promise對象,該對象有一個then方法,容許指定回調函數。好比,f1的回調函數f2,能夠寫成:
複製代碼
f1().then(f2); 
function f1(){
  var dfd = $.Deferred();
  setTimeout(function () {
    // f1的任務代碼
    dfd.resolve();
  }, 500);
  return dfd.promise;
} 
複製代碼
這樣寫的優勢在於,回調函數變成了鏈式寫法,程序的流程能夠看得很清楚。
好比,指定多個回調函數:f1().then(f2).then(f3); 
再好比,指定發生錯誤時的回調函數:f1().then(f2).fail(f3);
相關文章
相關標籤/搜索