socket通訊IOCP模型

來源:互聯網
上載者:User

標籤:

1.同步與非同步模式(Sync/Async)
在一些IO函數如ReadFile(),socket.recv(),預設使用的是同步模式,即函數執行完成後才返回,如果既沒有資料,也沒有逾時設定,則程式會阻塞在這裡。在對話方塊主程式中,如果使用這種方式會把介面卡死。

處理這類問題的常見方法是,啟動一個線程,將這些IO操作放線上程中執行。如果需要結束線程的阻塞狀態,只要在主線程中關閉Handle/Socket即可。

另一種處理方式為非同步模式,IO函數ReadFile()調用後直接返回,通過查詢狀態來擷取其執行結果,如:
HANDLE hFile = CreateFile(xx, GENERIC_READ, 0, NULL,...,FILE_FLAG_OVERLAPPED); //指定FILE_FLAG_OVERLAPPED
OVERLAPPED overlap;
ReadFile(hFile, buf,nsize, &nread, &overlap);//立即返回false,err=IO_PENDING
while(i<100 && !HasOverlappedIoCompleted(&overlap)); // 等待完成……
{ DoSomething();
  i++;Sleep(1000);//CancelIO(hFile)...
}
這種方式可以對阻塞過程進行控制,如逾時退出或做其他處理。

2.同步模式的多任務
以上兩種模式,在單個IO操作時區別不大,非同步模式更零活一些。在多任務的情況下,網路伺服器面向上萬的用戶端,同步模式則需要開啟上萬個線程來通訊
sockServer = socket(...);
_beginThread(Thread_Recving, ...);
Thread_Accepting()
{
  while(bRunning)
  {
    sockClient = accept(sockServer, ...); //blocking
    _beginThread(Thread_Recving, ...);
  }
}
Thread_Recving() // 10000+個線程
{
  while(bRunning)
  {
    recv(sockClient, ...); //blocking
    DoSomthing();
  }
}
這種方式非常消耗CPU和記憶體資源,系統在各個線程之間切換,效率很低。

3.非同步模式的多任務——IOCP
在上面的例子中,如果以非同步模式建立串連,以輪詢的方式來檢查各個串連是否收到資料
sockServer = socket(...);
_beginthread(Thread_Accepting, ...);
_beginthread(Thread_Recving, ...);
Thread_Accepting()
{
  while(bRunning)
  {
    sockClient[x] = accept(sockServer, ...); //non-blocking
    recv(sockClient[x], &overlap[x]);
  }
}
Thread_Recving()
{
  while(bRunning)
  {
    for(i=0; i<10000; i++)
    {
      if(HasOverlappedIoCompleted(&overlap[i]))
        DoSomthing(i);
    }
  }
}
這種方式顯然不可行,並發的時候,單個線程處理,如果DoSomthing(i)處理時間長,則很容易造成資料丟失未處理。
這種情況下,比較好的方法是IOCP(Complete Port).IIS,FTP等許多網路伺服器軟體,都是採用這種模式。首先根據CPU數量來建立線程串連池,可以利用網卡DMA等特性,直接將網路資料寫入記憶體,再動態調用線程來處理資料。

WSAStartup(MAKEWORD(2, 2), &wsaData); // WinSock 2.2
hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

sockSvr = socket(AF_INET, SOCK_STREAM, 0);
bind(m_sockSvr, (SOCKADDR*)&srvAddr, sizeof(SOCKADDR));
listen(m_sockSvr, 10);

CreateThread(Thread_Accepting, ...);
GetSystemInfo(&sysInfo);
for(i=0; i<sysInfo.dwNumberOfProcessors*2+2; i++)
  hThread[i] = CreateThread(NULL, 0, Thread_Recving, param, 0, NULL);

Thread_Accepting()
{
  while(bRunning)
  {
    sockClient[x] = accept(sockServer, ...); //non-blocking
    CreateIoCompletionPort(sockClient[x], hCompPort, param[x], 0); // 將IO對象sockClient[x]與hCompPort關聯
    WSARecv(sockClient, wsaBuf, 1, &dwSize, &dwFlag, &overLapped, NULL); //non-blocking
  }
}
Thread_Recving() // 4*2+2=10個線程
{
  while(bRunning)
  {
    GetQueuedCompletionStatus(hCompPort, &dwRecv, param, &pOverlap, INFINITE); //blocking
    DoSomthing(wsaBuf); // 資料已經接收進了記憶體
    WSARecv(sock, &wsaBuf, 1, &dwRecv, &dwFlag, &overLap, NULL); // continue recving
  }
}
這種方式的好處是,恰好利用了全部CPU的資源,因為啟動太多線程沒有意義,反而耗費資源進行線程切換。

socket通訊IOCP模型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.