1. 程式人生 > >多種SOKECT通訊模型的理解(select,WSAAsyncSelect,WSAEventSelect,Overlapped I/O 事件通知,Overlapped I/O 完成例程,IOCP)

多種SOKECT通訊模型的理解(select,WSAAsyncSelect,WSAEventSelect,Overlapped I/O 事件通知,Overlapped I/O 完成例程,IOCP)

老陳有一個在外地工作的女兒,不能經常回來,老陳和她通過信件聯絡。他們的信會被郵遞員投遞到他們的信箱裡。
  這和Socket模型非常類似。下面我就以老陳接收信件為例講解SocketI/O模型。
  一:select模型
  老陳非常想看到女兒的信。以至於他每隔10分鐘就下樓檢查信箱,看是否有女兒的信,在這種情況下,“下樓檢查信箱”然後回到樓上耽誤了老陳太多的時間,以至於老陳無法做其他工作。
  select模型和老陳的這種情況非常相似:周而復始地去檢查......如果有資料......接收/傳送.......
  使用執行緒來select應該是通用的做法: 
procedure TListenThread.Execute; 

var 
 addr : TSockAddrIn; 
 fd_read : TFDSet; 
 timeout : TTimeVal; 
 ASock, 
 MainSock : TSocket; 
 len, i : Integer; 
begin 
 MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 
 addr.sin_family := AF_INET; 
 addr.sin_port := htons(5678); 
 addr.sin_addr.S_addr := htonl(INADDR_ANY); 
 bind( MainSock, @addr, sizeof(addr) ); 

 listen( MainSock, 5 ); 
 while (not Terminated) do 
 begin 
  FD_ZERO( fd_read ); 
  FD_SET( MainSock, fd_read ); 
  timeout.tv_sec := 0; 
  timeout.tv_usec := 500; 
  if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //至少有1個等待Accept的connection 
  begin 
   if FD_ISSET( MainSock, fd_read ) then 
   begin 
   for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是說select只能同時管理最多64個連線 

   begin 
    len := sizeof(addr); 
    ASock := accept( MainSock, addr, len ); 
    if ASock <> INVALID_SOCKET then 
     ....//為ASock建立一個新的執行緒,在新的執行緒中再不停地select 
    end; 
   end;    
  end; 
 end; //while (not self.Terminated) 
 shutdown( MainSock, SD_BOTH ); 
 closesocket( MainSock ); 
end; 
  二:WSAAsyncSelect模型
  後來,老陳使用了微軟公司的新式信箱。這種信箱非常先進,一旦信箱裡有新的信件,蓋茨就會給老陳打電話:喂,大爺,你有新的信件了!從此,老陳再也不必頻繁上下樓檢查信箱了,牙也不疼了,你瞅準了,藍天......不是,微軟......
  微軟提供的WSAAsyncSelect模型就是這個意思。
  WSAAsyncSelect模型是Windows下最簡單易用的一種Socket I/O模型。使用這種模型時,Windows會把網路事件以訊息的形勢通知應用程式。
  首先定義一個訊息標示常量: 
const WM_SOCKET = WM_USER + 55; 
  再在主Form的private域新增一個處理此訊息的函式宣告: 
private 
procedure WMSocket(var Msg: TMessage); message WM_SOCKET; 
  然後就可以使用WSAAsyncSelect了: 
var 
 addr : TSockAddr; 
 sock : TSocket; 
 sock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 
 addr.sin_family := AF_INET; 
 addr.sin_port := htons(5678); 
 addr.sin_addr.S_addr := htonl(INADDR_ANY); 
 bind( m_sock, @addr, sizeof(SOCKADDR) ); 
 WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE ); 
 listen( m_sock, 5 ); 
 .... 
  應用程式可以對收到WM_SOCKET訊息進行分析,判斷是哪一個socket產生了網路事件以及事件型別: 
procedure TfmMain.WMSocket(var Msg: TMessage); 
var 
 sock : TSocket; 
 addr : TSockAddrIn; 
 addrlen : Integer; 
 buf : Array [0..4095] of Char; 
begin 
 //Msg的WParam是產生了網路事件的socket控制代碼,LParam則包含了事件型別 
 case WSAGetSelectEvent( Msg.LParam ) of 
 FD_ACCEPT : 
  begin 
   addrlen := sizeof(addr); 
   sock := accept( Msg.WParam, addr, addrlen ); 
   if sock <> INVALID_SOCKET then 
    WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE ); 
  end; 
  FD_CLOSE : closesocket( Msg.WParam ); 
  FD_READ : recv( Msg.WParam, buf[0], 4096, 0 ); 
  FD_WRITE : ; 
 end; 
end; 
  三:WSAEventSelect模型
  後來,微軟的信箱非常暢銷,購買微軟信箱的人以百萬計數......以至於蓋茨每天24小時給客戶打電話,累得腰痠背痛,喝蟻力神都不好使。微軟改進 了他們的信箱:在客戶的家中新增一個附加裝置,這個裝置會監視客戶的信箱,每當新的信件來臨,此裝置會發出“新信件到達”聲,提醒老陳去收信。蓋茨終於可以睡覺了。
  同樣要使用執行緒: 
procedure TListenThread.Execute; 
var 
 hEvent : WSAEvent; 
 ret : Integer; 
 ne : TWSANetworkEvents; 
 sock : TSocket; 
 adr : TSockAddrIn; 
 sMsg : String; 
 Index, 
 EventTotal : DWORD; 
 EventArray : Array [0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT; 
begin 
 ...socket...bind... 
 hEvent := WSACreateEvent(); 
 WSAEventSelect( ListenSock, hEvent, FD_ACCEPT or FD_CLOSE ); 
 ...listen... 
 while ( not Terminated ) do 
 begin 
  Index := WSAWaitForMultipleEvents( EventTotal, @EventArray[0], FALSE, WSA_INFINITE, FALSE ); 
  FillChar( ne, sizeof(ne), 0 ); 
  WSAEnumNetworkEvents( SockArray[Index-WSA_WAIT_EVENT_0], EventArray[Index-WSA_WAIT_EVENT_0], @ne ); 
  if ( ne.lNetworkEvents and FD_ACCEPT ) > 0 then 
  begin 
   if ne.iErrorCode[FD_ACCEPT_BIT] <> 0 then 
    continue; 
   ret := sizeof(adr); 
   sock := accept( SockArray[Index-WSA_WAIT_EVENT_0], adr, ret ); 
   if EventTotal > WSA_MAXIMUM_WAIT_EVENTS-1 then//這裡WSA_MAXIMUM_WAIT_EVENTS同樣是64 
   begin 
    closesocket( sock ); 
    continue; 
   end; 
   hEvent := WSACreateEvent(); 
   WSAEventSelect( sock, hEvent, FD_READ or FD_WRITE or FD_CLOSE ); 
   SockArray[EventTotal] := sock; 
   EventArray[EventTotal] := hEvent; 
   Inc( EventTotal ); 
  end; 
  if ( ne.lNetworkEvents and FD_READ ) > 0 then 
  begin 
   if ne.iErrorCode[FD_READ_BIT] <> 0 then 
    continue; 
    FillChar( RecvBuf[0], PACK_SIZE_RECEIVE, 0 ); 
    ret := recv( SockArray[Index-WSA_WAIT_EVENT_0], RecvBuf[0], PACK_SIZE_RECEIVE, 0 ); 
    ...... 
   end; 
  end; 
end; 

四:Overlapped I/O 事件通知模型
  後來,微軟通過調查發現,老陳不喜歡上下樓收發信件,因為上下樓其實很浪費時間。於是微軟再次改進他們的信箱。新式的信箱採用了更為先進的技術,只要使用者告訴微軟自己的家在幾樓幾號,新式信箱會把信件直接傳送到使用者的家中,然後告訴使用者,你的信件已經放到你的家中了!老陳很高興,因為他不必再親自收發信件了!
  Overlapped I/O 事件通知模型和WSAEventSelect模型在實現上非常相似,主要區別在“Overlapped”,Overlapped模型是讓應用程式使用重疊資料結構(WSAOVERLAPPED),一次投遞一個或多個Winsock I/O請求。這些提交的請求完成後,應用程式會收到通知。什麼意思呢?就是說,如果你想從socket上接收資料,只需要告訴系統,由系統為你接收資料,而你需要做的只是為系統提供一個緩衝區~~~~~
Listen執行緒和WSAEventSelect模型一模一樣,Recv/Send執行緒則完全不同: 
procedure TOverlapThread.Execute; 
var 
 dwTemp : DWORD; 
 ret : Integer; 
 Index : DWORD; 
begin 
 ...... 
 while ( not Terminated ) do 
 begin 
  Index := WSAWaitForMultipleEvents( FLinks.Count, @FLinks.Events[0], FALSE, RECV_TIME_OUT, FALSE ); 
  Dec( Index, WSA_WAIT_EVENT_0 ); 
  if Index > WSA_MAXIMUM_WAIT_EVENTS-1 then //超時或者其他錯誤 
   continue; 
  WSAResetEvent( FLinks.Events[Index] ); 
  WSAGetOverlappedResult( FLinks.Sockets[Index], FLinks.pOverlaps[Index], @dwTemp, FALSE,FLinks.pdwFlags[Index]^ ); 

相關推薦

多種SOKECT通訊模型理解select,WSAAsyncSelect,WSAEventSelect,Overlapped I/O 事件通知,Overlapped I/O 成例,IOCP

老陳有一個在外地工作的女兒,不能經常回來,老陳和她通過信件聯絡。他們的信會被郵遞員投遞到他們的信箱裡。  這和Socket模型非常類似。下面我就以老陳接收信件為例講解SocketI/O模型。  一:select模型  老陳非常想看到女兒的信。以至於他每隔10分鐘就下樓檢查信

windows下多路複用IOselect,WSAAsyncSelect,WSAEventSelect

Winsock提供的程式設計介面中socket預設是阻塞的,比如send,recv,connect,可以通過ioctlsocket進行設定非阻塞,server端要管理多個連線可能不是一件容易的事,windows下提供了不少模型可供使用,比如標題的三個,然後完成埠,libeve

對於網路通訊理解

所有的網路服務均基於網路網路通訊的基礎之上。 SOCKET模組的封裝將TCP/IP協議棧劃分成兩個介面 1、應用層介面: 只需要完成應用服務專屬協議的開發,將底層網路看成直連裝置,不再考慮任何路由交換的內容,此層面主要是軟體工程師的工作介面。 2、路由交換介面: 需要完成TCP/IP協議棧四層及以下各層的路由

socket通訊之七:Overlapped I/O 成例模型實現的客戶/伺服器模型

前一篇介紹了重疊IO的一種實現方式即基於事件通知的方式,這一篇介紹另外一種方式,即使用完成例程的方式實現重疊IO,首先宣告這種方式比事件通知的方式簡單多了。 用完成例程來實現重疊I/O比用事件通知簡單得多。在這個模型中,主執行緒只用不停的接受連線即可;輔助執行緒判斷有沒有

windows下的IO模型之選擇select模型

工作者線程 dfs read 沒有 應用 ould 設置 spa fine 1.選擇(select)模型:選擇模型:通過一個fd_set集合管理套接字,在滿足套接字需求後,通知套接字。讓套接字進行工作。避免套接字進入阻塞模式,進行無謂的等待。選擇模型的核心的FD_SET集合

通俗理解N-gram語言模型

資料 簡化 事情 自然 自然語言 規模 什麽 發音 給定 N-gram語言模型 考慮一個語音識別系統,假設用戶說了這麽一句話:“I have a gun”,因為發音的相似,該語音識別系統發現如下幾句話都是可能的候選:1、I have a gun. 2、I have a gu

I/0模型select模型

select 模型 1)引入 為什麼要引入select模型呢  同步阻塞問題我們可以利用多執行緒 或者把socket改成非阻塞 當我們要接受資料的時候我們要來回檢視接受緩衝區有沒有資料這樣我們就要來回切換使用者和核心浪費時間降低效率 所以我們讓一個把所有的socket的有無資料都看

OSI模型中物理層的通訊形式總結

一、主機之間的資訊的互動方式 1. 單向通訊(單工通訊) 即只能有一個方向的通訊而沒有反方向的互動。無線電廣播或有線電廣播以及電視廣播就屬於這種型別。 2.雙向交替通訊(半雙工通訊) 即通訊的雙方都可以傳送資訊,但不能同時傳送(也不能同時接收)。這種通訊方式是一方傳送另一方接收,

Linux下網路socket程式設計——實現伺服器select與多個客戶端通訊

Linux下網路socket程式設計——實現伺服器(select)與多個客戶端通訊 置頂 2017年06月23日 14:44:37 閱讀數:3225 標籤: socket程式設計伺服器與多個客戶端通epoll多路複用C語言網路程式設計 更多

detectron程式碼理解:Resnet模型構建理解

這裡具體以resnet50為例進行說明,一句一句地分析程式碼,程式碼位置位於Resnet.py,具體的分析函式為add_ResNet_convX_body. 在分析之前首先貼上resnet50的程式碼結構圖: # add the stem (by default, conv1 and

detectron程式碼理解:FPN模型構建

1.FPN的原理 FPN的原理示意圖如下,上述包括一個自底向上的線路,一個自頂向下的線路,橫向連線(lateral connection),圖中放大的區域就是橫向連線。 自底向上的路徑:自下而上的路徑是卷積網路的前饋計算,在前向過程中,feature map的大小在經過某些層後會改變,

模型的一些理解從決策樹到GBDT

1.決策樹 基本流程: 整體是一個遞迴的過程,返回條件有三種: 當前結點中所有樣本的類別都為c,返回值為c; 當前結點中樣本集合為空,此時返回父結點中類別數最多的類。把父節點的樣本分佈作為先驗 當前結點中樣本的屬性集合為空,或者所有樣本屬性取值相同,將當前結點

網路通訊過程--解析:IP地址, 埠port,,DNS伺服器,MAC地址,預設閘道器,通訊過程圖解理解

IP地址: 用來在網路中標記一臺電腦,指引資料包的收發方向,在一個區域網中是唯一的;電腦中的ip是可以手動修改的,只要在同一個區域網中不重複即可。 分類: ①ip地址的組成,包括網路地址和主機地址

IO通訊模型同步阻塞模式BIOBlocking IO

幾個概念 阻塞IO 和非阻塞IO 這兩個概念是程式級別的。主要描述的是程式請求作業系統IO操作後,如果IO資源沒有準備好,那麼程式該如何處理的問題:前者等待;後者繼續執行(但是使用執行緒一直輪詢,直到有IO資源準備好了)。 同步IO 和 非同步IO,這兩個概念是作業系統級別的。主要描述的是作業系統在收到程式

IO通訊模型同步非阻塞模式NIONonBlocking IO

同步非阻塞模式(NonBlocking IO) 在非阻塞模式中,發出Socket的accept()和read()操作時,如果核心中的資料還沒有準備好,那麼它並不會阻塞使用者程序,而是立刻返回一個資訊。也就是說程序發起一個read操作後,並不需要一直阻塞等待,而是馬上就得到了一個結果。 如果結果發現數據準備

IO通訊模型多路複用IO

多路複用IO 從非阻塞同步IO的介紹中可以發現,為每一個接入建立一個執行緒在請求很多的情況下不那麼適用了,因為這會漸漸耗盡伺服器的資源,人們也都意識到了這個 問題,因此終於有人發明了IO多路複用。最大的特點就是不需要開那麼多的執行緒和程序。 多路複用IO是指使

貝葉斯模型理解2

讀了之前一篇文章,應該對先驗資訊和最大似然函式有了一定的理解,那下面來說貝葉斯模型最後一個總要概念:後驗概率。 在上篇文章中,我們通過求解似然函式的概率最大值,求得了引數r,大家還會發現,提前拋硬幣的次數不同,r最後的取值是不同的。 大家記住這個公式:後驗概

socket通訊之五:select多路複用的客戶/伺服器模型

前面一篇介紹了伺服器端使用多執行緒的方式來處理多個客戶端的請求的,但是當客戶端數量增多時執行緒數量會急劇增加,導致消耗大量的資源。 於是就引出了伺服器端的一種新的模型。 1. 阻塞與非阻塞 首先介紹幾個基本的概念。 阻塞方式( block ),顧名思義,就是程序或是

對於JVM記憶體模型理解對比jdk1.7與1.8

首先介紹一下java虛擬機器規範所規定的java記憶體模型:1.程式計數器(java記憶體模型中唯一不會發生oom的空間),負責記錄正在執行的虛擬機器位元組碼地址,如果是native方法,則計數器值為空,執行緒私有區2.java虛擬機器棧,生命週期與執行緒相同。描述java方

使用Encoder-Decoder模型自動生成對聯的思路——encode-decoder理解3

|Encoder-Decoder模型 Encoder-Decoder框架可以看作是一種文字處理領域的研究模式,應用場景異常廣泛。下圖是文字處理領域裡常用的Encoder-Decoder框架最抽象的一種表示: