淺談C#網絡編程(二)

閱讀目錄:緩存

  1. 異步IO
  2. 非阻塞式同步IO
  3. 基於回調的異步IO併發

異步IO

上篇提到用多線程處理多個阻塞同步IO而實現併發服務端,這種模式在鏈接數量比較小的時候很是適合,一旦鏈接過多,性能會急速降低。 在大多數服務端網絡軟件中會採用一種異步IO的方式來提升性能。網絡

  • 同步IO方式:鏈接Receive請求->等待->等待->接收成功
  • 異步IO方式:鏈接Receive請求->當即返回->事件或回調通知

採用異步IO方式,意味着單線程能夠處理多個請求了,鏈接發起一個Receive請求後,當前線程能夠當即去作別的事情,當數據接收完畢通知線程處理便可。
其數據接收分2部分:多線程

  1. 數據從別的機器發送內核緩衝區
  2. 內核緩衝區拷貝到用戶緩衝區

第二部分示例代碼:併發

byte[] msg = new byte[256]; socket.Receive(msg);

介紹這2部分的目的是方便區分其餘幾種方式。 對於用戶程序來講,同步IO和異步IO的區別在於第二部分是否須要等待。異步

非阻塞式同步IO

非阻塞式同步IO,由同步IO延伸出來,把這個名詞拆分紅2部分描述:socket

  1. 非阻塞式,指的是上節"數據從別的機器發送內核緩衝區"部分是非阻塞的。
  2. 同步IO,指的是上節"內核緩衝區拷貝到用戶緩衝區"部分是等待的。

既然是第一部分是非阻塞的,那就須要一種方法得知何時內核緩衝區是OK的。 設置非阻塞模式後,在鏈接調用Receive方法時,會當即返回一個標記,告知用戶程序內核緩存區有沒有數據,若是有數據開始進行第二部分操做,從內核緩衝區拷貝到用戶程序緩衝區。 因爲系統會返回個標記,那能夠經過輪詢方式來判斷內核緩衝區是否OK。函數

設置非阻塞模式參考代碼:性能

SocketInformation sif=new SocketInformation();
sif.Options=SocketInformationOptions.NonBlocking;
sif.ProtocolInformation = new byte[24];
Socket socket = new Socket(sif);

輪詢參考代碼:spa

while(true) 
{
byte[] msg = new byte[256];
var temp = socket.Receive(msg);
if (temp=="OK"){
//do something
}else{ continue }
}

 這種方式近乎淘汰了,瞭解便可。線程

基於回調的異步IO

上面介紹過:

  • 異步IO方式:鏈接Receive請求->當即返回->事件或回調通知

當回調到執行時,數據已經在用戶程序緩衝區已經準備好了,在回調代碼中對這部分數據進行相應的邏輯便可。

發出接收請求:

 static byte[] msg = new byte[256]; var temp = socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(ReadCallback), socket);

回調函數中對數據作處理:

public static void ReadCallback(IAsyncResult ar) 
{ 
var socket = (Socket)ar.AsyncState;
 int read = socket.EndReceive(ar);
DoSomething(msg); 
socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(Read_Callback), socket);
}

 當回調函數執行時,表示數據已經準備好,須要先結束接收請求EndReceive,以便第二次發出接收請求。 在服務端程序中要處理多個客戶端的接收,再次發出BeginReceive接收數據請求便可。

這裏的回調函數是在另一個線程的觸發,必要時要對數據加鎖防止數據競爭:

Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
相關文章
相關標籤/搜索