完成埠是套接字的一種模型。利用套接字的完成埠模型,可以在套接字上實現重疊i/o操作。
在傳統的c/s模式中,一旦有客戶端連線服務端,服務端將建立乙個執行緒來處理與該客戶端的i/o操作。如果有多個客戶端連線服務端時,服務端將會建立多個執行緒。多個執行緒間的切換會佔據cpu的大量處理時間,而執行緒的建立和銷毀也會消耗大量的cpu時間。
可以通過完成埠模型避免以上問題。完成埠模型並沒有為每乙個連線服務端的客戶端都建立乙個對應的執行緒。在該模型中,當有客戶端的i/o請求完成之後,會向完成埠傳送訊息。完成埠模型利用執行緒池中的執行緒在完成埠中取出該訊息進行處理,在訊息處理完之後,執行緒池中的執行緒變為休眠狀態繼續等待完成埠中的訊息。
圖1 完成埠模型基本流程
從圖1可以看出,服務端僅使用執行緒池中少量的執行緒來處理客戶端的i/o請求。這樣就避免了多個執行緒切換以及建立銷毀執行緒帶來的時間消耗。
從「1完成埠簡介」中分析可知,完成埠模型主要實現了完成埠的建立、完成埠與套接字i/o的關聯以及從完成埠佇列中取出訊息等功能。以上功能主要涉及到兩個函式,乙個是createiocompletionport()函式,另外乙個是getqueuedcompletionstatus()函式。
該函式主要實現完成埠的建立和完成埠與套接字i/o的關聯等功能。該函式的格式為
handle winapi createiocompletionport(
handle filehandle
, handle existingcompletionport
, ulong_ptr completionkey
, dword numberofconcurrentthreads
);
該函式的第乙個引數filehandle表示開啟檔案的控制代碼,該檔案用於重疊i/o的完成,這裡的「檔案」指的是windows的核心物件,套接字也屬於「檔案」;第二個引數existingcompletionport指定了i/o完成埠的控制代碼;第三個引數completionkey指定了檔案的完成鍵,在完成鍵中包含了指定檔案的每個i/o完成包;numberofconcurrentthreads指定了同時處理i/o完成包的執行緒的最大數量。
1使用createiocompletionport()函式建立完成埠時,引數filehandle設定為invalid_handle_value,existingcompletionport和completionkey設定為null,numberofconcurrentthreads設定為0即可;
2完成鍵可以看作是使用者自定義數值的指標,這個自定義的數值會交給「1.2 完成埠模型基本原理」中提到的執行緒池中的服務執行緒,服務執行緒得到該指標後,可以使用該指標指向的記憶體中的資料,完成了主線程與服務執行緒之間的通訊。
該函式的作用是從i/o完成埠佇列中取出完成包訊息。getqueuedcompletionstatus()函式一般在「1.2 完成埠模型基本原理」中提到的執行緒池中的服務執行緒中呼叫。
bool winapi getqueuedcompletionport(
handle completionport
, lpdword lpnumberofbytes
, pulong_ptr lpcomletionkey
, dword dwmilliseconds
);
VS2015套接字程式設計斷開套接字連線
當服務端和客戶端結束了傳送接收資料之後,兩端連線的套接字就可以斷開了。斷開已連線的套接字主要分為三個步驟 首先關閉套接字的傳送和接收資料功能,接下來關閉套接字,最後釋放winsock動態庫資源。通過shutdown 函式關閉套接字的傳送和接收資料的功能。該函式的格式為 int shutdown so...
套接字 實現埠重用
假如埠被socket使用過,並且利用socket.close 來關閉連線,但此時埠還沒有釋放,要經過乙個time wait的過程之後才能使用,這是tnn的相當煩銀的,為了實現埠的馬上覆用,可以選擇setsockopt 函式來達到目的。以下是網上找到的一篇文章的一小段相關例子,試用之後,相當有效果,特...
VS2015中基於TCP客戶端的實現
在 vs2015中基於tcp服務端的實現 中實現了基於tcp的服務端。服務端通過呼叫listen 函式將套接字設定為監聽模式,並且呼叫accept 函式等待客戶端的連線。在基於tcp的客戶端中,主要的流程包括建立客戶端套接字和連線服務端兩個步驟。通過socket 函式建立用於客戶端的套接字。sock...