亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

c# AcceptEx與完成端口(IOCP)結(jié)合的示例

 更新時(shí)間:2021年03月09日 11:57:58   作者:源之緣  
這篇文章主要介紹了c# AcceptEx與完成端口(IOCP)結(jié)合的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下

前言

在windows平臺(tái)下實(shí)現(xiàn)高性能網(wǎng)絡(luò)服務(wù)器,iocp(完成端口)是唯一選擇。編寫網(wǎng)絡(luò)服務(wù)器面臨的問題有:

1 快速接收客戶端的連接。

2 快速收發(fā)數(shù)據(jù)。

3 快速處理數(shù)據(jù)。本文主要解決第一個(gè)問題。

AcceptEx函數(shù)定義

BOOL AcceptEx(
 SOCKET  sListenSocket,
 SOCKET  sAcceptSocket,
 PVOID  lpOutputBuffer,
 DWORD  dwReceiveDataLength,
 DWORD  dwLocalAddressLength,
 DWORD  dwRemoteAddressLength,
 LPDWORD  lpdwBytesReceived,
 LPOVERLAPPED lpOverlapped
);

為什么要用AcceptEx

  傳統(tǒng)的accept函數(shù)能滿足大部分場(chǎng)景的需要;但在某些極端條件下,必須使用acceptEx來(lái)實(shí)現(xiàn)。兩個(gè)函數(shù)的區(qū)別如下:

  1)accept是阻塞的;在一個(gè)端口監(jiān)聽,必須啟動(dòng)一個(gè)專用線程調(diào)用accept。當(dāng)然也可以用迂回的方式,繞過(guò)這個(gè)限制,處理起來(lái)會(huì)很麻煩,見文章單線程實(shí)現(xiàn)同時(shí)監(jiān)聽多個(gè)端口。acceptEx是異步的,可以同時(shí)對(duì)很多端口監(jiān)聽(監(jiān)聽端口的數(shù)量沒有上限的限制)。采用迂回的方式,使用accept監(jiān)聽,一個(gè)線程最多監(jiān)聽64個(gè)端口。這一點(diǎn)可能不是AcceptEx最大優(yōu)點(diǎn),畢竟同時(shí)對(duì)多個(gè)端口監(jiān)聽的情況非常少見。

 2)AcceptEx可以返回更多的數(shù)據(jù)。a)AcceptEx可以返回本地和對(duì)方ip地址和端口;而不需要調(diào)用函數(shù)getsockname和getpeername獲取網(wǎng)絡(luò)地址了。b)AcceptEx可以再接收到一段數(shù)據(jù)后,再返回。這種做法有利有弊,一般不建議這樣做。

 3)AcceptEx是先準(zhǔn)備套接字(socket)后接收。為了應(yīng)對(duì)突發(fā)的連接高峰,可以多次投放AcceptEx。accept是事后建立SOCKET,就是tcp三次握手完成后,accept調(diào)用才返回,再生成socket。生成套接字是相對(duì)比較耗時(shí)的操作,accept的方式無(wú)法及時(shí)處理突發(fā)連接。對(duì)于AcceptEx的處理方式為建議做如下處理:一個(gè)線程負(fù)責(zé)創(chuàng)建socket,一個(gè)線程負(fù)責(zé)處理AcceptEx返回。

以上僅僅通過(guò)文字說(shuō)明了AcceptEx的特點(diǎn)。下面通過(guò)具體代碼,逐一剖析。我將AcceptEx的處理封裝到類IocpAcceptEx中。編寫該類時(shí),盡量做到高內(nèi)聚低耦合,使該類可以方便的被其他模塊使用。

IocpAcceptEx外部功能說(shuō)明

class IocpAcceptEx
{
public:
 IocpAcceptEx();
 ~IocpAcceptEx();

 //設(shè)置回調(diào)接口。當(dāng)accept成功,調(diào)用回調(diào)接口。
 void SetCallback(IAcceptCallback* callback);
 // 增加監(jiān)聽端口
 void AddListenPort(UINT16 port);
 //啟動(dòng)服務(wù)
 BOOL Start();
 void Stop();
  。。。以下代碼省略
}
#define POST_ACCEPT 1
//使用IocpAcceptEx類,必須實(shí)現(xiàn)該接口。接收客戶端的連接
class IAcceptCallback
{
public:
 virtual void OnAcceptClient(SOCKET hSocketClient, UINT16 nListenPort) = 0;
};

該類的調(diào)用函數(shù)很簡(jiǎn)單,對(duì)外接口也很明確。說(shuō)明該類的職責(zé)很清楚,這也符合單一職責(zé)原則。

實(shí)現(xiàn)步驟說(shuō)明

AcceptEx不但需要與監(jiān)聽端口綁定,還需要與完成端口綁定。所以程序的第一步是創(chuàng)建完成端口:

a)創(chuàng)建完成端口

m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
if (m_hIocp == NULL)
  return FALSE;

b)監(jiān)聽端口創(chuàng)建與綁定

//生成套接字
 SOCKET serverSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
 if (serverSocket == INVALID_SOCKET)
 {
  return false;
 }

 //綁定
 SOCKADDR_IN addr;
 memset(&addr, 0, sizeof(addr));
 addr.sin_family = AF_INET;
 addr.sin_addr.s_addr = INADDR_ANY ;
 addr.sin_port = htons(port);
 if (bind(serverSocket, (sockaddr *)&addr, sizeof(addr)) != 0)
 {
  closesocket(serverSocket);
  serverSocket = INVALID_SOCKET;
  return false;
 }

 //啟動(dòng)監(jiān)聽
 if (listen(serverSocket, SOMAXCONN) != 0)
 {
  closesocket(serverSocket);
  serverSocket = INVALID_SOCKET;
  return false;
 }

 //監(jiān)聽端口與完成端口綁定
 if (CreateIoCompletionPort((HANDLE)serverSocket, m_hIocp, (ULONG_PTR)this, 0) == NULL)
 {
  closesocket(serverSocket);
  serverSocket = INVALID_SOCKET;
  return false;
 }

c)投遞AcceptEx

struct AcceptOverlapped
{
 OVERLAPPED  overlap;
 INT32 opType;
 SOCKET serverSocket;
 SOCKET clientSocket;

 char lpOutputBuf[128];
 DWORD dwBytes;
};

int IocpAcceptEx::NewAccept(SOCKET serverSocket)
{
 //創(chuàng)建socket
 SOCKET _socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 

 AcceptOverlapped *ov = new AcceptOverlapped();
 ZeroMemory(ov,sizeof(AcceptOverlapped));
 ov->opType = POST_ACCEPT;
 ov->clientSocket = _socket;
 ov->serverSocket = serverSocket;

 //存放網(wǎng)絡(luò)地址的長(zhǎng)度
 int addrLen = sizeof(sockaddr_in) + 16;

 int bRetVal = AcceptEx(serverSocket, _socket, ov->lpOutputBuf,
  0,addrLen, addrLen,
  &ov->dwBytes, (LPOVERLAPPED)ov);
 if (bRetVal == FALSE)
 {
  int error = WSAGetLastError();
  if (error != WSA_IO_PENDING)
  {
   closesocket(_socket);
   return 0;
  }
 }

 return 1;
}

AcceptEx是非阻塞操作,調(diào)用會(huì)立即返回。當(dāng)有客戶端連接時(shí),怎么得到通知。答案是通過(guò)完成端口返回。注意有一個(gè)步驟:監(jiān)聽端口與完成端口綁定,就是serverSocket與m_hIocp綁定,所以當(dāng)有客戶端連接serverSocket時(shí),m_hIocp會(huì)得到通知。需要生成線程,等待完成端口的通知。

d)通過(guò)完成端口,獲取通知

DWORD dwBytesTransferred;
 ULONG_PTR Key;
 BOOL rc;
 int error;

 AcceptOverlapped *lpPerIOData = NULL;
 while (m_bServerStart)
 {
  error = NO_ERROR;
  rc = GetQueuedCompletionStatus(
   m_hIocp,
   &dwBytesTransferred,
   &Key,
   (LPOVERLAPPED *)&lpPerIOData,
   INFINITE);

  if (rc == FALSE)
  {
   error = 0;
   if (lpPerIOData == NULL)
   {
    DWORD lastError = GetLastError();
    if (lastError == WAIT_TIMEOUT)
    {
     continue;
    }
    else
    {
     assert(false);
     return lastError;
    }
   }
  }
  if (lpPerIOData != NULL)
  {
   switch (lpPerIOData->opType)
   {
   case POST_ACCEPT:
   {
    OnIocpAccept(lpPerIOData, dwBytesTransferred, error);
   }
   break;
   }
  }
  else 
  {   
  }
 }
 return 0;
DWORD WINAPI IocpAcceptEx::AcceptExThreadPool(PVOID pContext)
{
 ThreadPoolParam *param = (ThreadPoolParam*)pContext;
 param->pIocpAcceptEx->NewAccept(param->ServeSocket);
 delete param;
 return 0;
}

int IocpAcceptEx::OnIocpAccept(AcceptOverlapped *acceptData, int transLen, int error)
{
 m_IAcceptCallback->OnAcceptClient(acceptData->clientSocket, acceptData->serverSocket);

 //當(dāng)一個(gè)AcceptEx返回,需要投遞一個(gè)新的AcceptEx。 
 //使用線程池好像有點(diǎn)小題大做。前文已說(shuō)過(guò),套接字的創(chuàng)建相對(duì)是比較耗時(shí)的操作。
 //如果不在線程池投遞AcceptEx,AcceptEx的優(yōu)點(diǎn)就被抹殺了。
 ThreadPoolParam *param = new ThreadPoolParam();
 param->pIocpAcceptEx = this;
 param->ServeSocket = acceptData->serverSocket;
 QueueUserWorkItem(AcceptExThreadPool, this, 0);

 delete acceptData;
 return 0;
}

后記

采用完成端口是提高IO處理能力的一個(gè)途徑(廣義上講,通訊操作也是IO)。為了提高IO處理能力,windows提供很多異步操作函數(shù),這些函數(shù)都與完成端口關(guān)聯(lián),所以這一類處理的思路基本一致。學(xué)會(huì)了AcceptEx的使用,可以做到觸類旁通的效果。

以上就是c# AcceptEx與完成端口(IOCP)結(jié)合的示例的詳細(xì)內(nèi)容,更多關(guān)于c# AcceptEx與完成端口(IOCP)結(jié)合的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C# 拓展方法的簡(jiǎn)單實(shí)例

    C# 拓展方法的簡(jiǎn)單實(shí)例

    這篇文章介紹了C# 拓展方法的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下
    2013-08-08
  • C#向Word文檔中添加內(nèi)容控件的方法示例

    C#向Word文檔中添加內(nèi)容控件的方法示例

    這篇文章主要給大家介紹了C#向Word文檔中添加內(nèi)容控件的方法,文中對(duì)各種不同控件的添加方法分別進(jìn)行了介紹,如組合框、文本、圖片、日期選取器及下拉列表等內(nèi)容控件,都給出了詳細(xì)的示例代碼,有需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-01-01
  • C#反色處理及其效率問題分析

    C#反色處理及其效率問題分析

    這篇文章主要介紹了C#反色處理及其效率問題分析,實(shí)例分析了C#反色處理問題的技巧及相關(guān)效率問題,需要的朋友可以參考下
    2015-06-06
  • c#讀取文件詳談

    c#讀取文件詳談

    你平時(shí)是怎么讀取文件的?使用流讀取。是的沒錯(cuò),C#給我們提供了非常強(qiáng)大的類庫(kù)(又一次吹捧了.NET一番)
    2013-09-09
  • C#實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入到SQL server數(shù)據(jù)庫(kù)

    C#實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入到SQL server數(shù)據(jù)庫(kù)

    這篇文章主要為大家詳細(xì)介紹了在C#中如何實(shí)現(xiàn)Excel數(shù)據(jù)導(dǎo)入到SQL server數(shù)據(jù)庫(kù)中,文中的示例代碼簡(jiǎn)潔易懂,希望對(duì)大家有一定的幫助
    2024-03-03
  • vscode設(shè)置Fira_Code字體及改變編輯器字體、背景顏色的代碼詳解

    vscode設(shè)置Fira_Code字體及改變編輯器字體、背景顏色的代碼詳解

    這篇文章主要介紹了vscode設(shè)置Fira_Code字體及改變編輯器字體、背景顏色,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • C#中數(shù)組初始化、反轉(zhuǎn)和排序用法實(shí)例

    C#中數(shù)組初始化、反轉(zhuǎn)和排序用法實(shí)例

    這篇文章主要介紹了C#中數(shù)組初始化、反轉(zhuǎn)和排序用法,涉及C#中數(shù)組常見的定義、初始化、排序等操作技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • C# 實(shí)現(xiàn)QQ式截圖功能實(shí)例代碼

    C# 實(shí)現(xiàn)QQ式截圖功能實(shí)例代碼

    本篇文章主要介紹了C# 實(shí)現(xiàn)QQ式截圖功能實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • C#實(shí)現(xiàn)將javascript文件編譯成dll文件的方法

    C#實(shí)現(xiàn)將javascript文件編譯成dll文件的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)將javascript文件編譯成dll文件的方法,涉及C#編譯生成dll動(dòng)態(tài)鏈接庫(kù)文件的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • 輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句

    輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句

    輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句,  C#語(yǔ)言提供了一個(gè)for語(yǔ)句循環(huán)的捷徑,而且還促進(jìn)了集合類的更為一致,就是本文提到的foreach語(yǔ)句,感興趣的小伙伴們可以參考一下
    2015-11-11

最新評(píng)論