socket IOCP

  1. //---------------------------------------------------------------------------
  2. #include <vcl.h>
  3. #pragma hdrstop
  4. #include "thrListen.h"
  5. #include "Unit1.h"
  6. #pragma package(smart_init)
  7. #pragma comment(lib,"ws2_32.lib")
  8. //---------------------------------------------------------------------------
  9. __fastcall TListenThread::TListenThread(bool CreateSuspended)
  10.   : TThread(CreateSuspended)
  11. {
  12. }
  13. //---------------------------------------------------------------------------
  14. void __fastcall TListenThread::Execute()
  15. {
  16.   //---- Place thread code here ----
  17.   SYSTEM_INFO  si ;
  18.   Integer  i ;
  19.   HANDLE  hThread ;
  20.   DWORD  ThreadID ;
  21.   SOCKET  AConnect ;
  22.   sockaddr_in  addr ;
  23.   Integer  len ;
  24.   DWORD  BytesRecv,  Flags;
  25.   PPER_OPERATION_DATA  pPerIoDat ;
  26. //  FCompletPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0,0,0 );
  27.   if((FCompletPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0))==NULL)
  28.   {
  29.     MessageBox(0, "CreateIoCompletionPort failed.""Error", MB_OK +
  30.         MB_ICONINFORMATION);
  31.     return;
  32.   }
  33.   GetSystemInfo( &si ); 
  34.   for ( i=0 ;i<si.dwNumberOfProcessors;i++ ) 
  35.   {
  36. //    hThread = CreateThread( NULL,0,&WorkerThread,(void *)(FCompletPort),0,ThreadID );
  37.     if
  38.     (
  39.       ( hThread=CreateThread(NULL,0,WorkerThread,FCompletPort,0,&ThreadID) )
  40.       == NULL
  41.     )
  42.     {
  43.       MessageBox(0, "CreateThread() failed with error.""Error", MB_OK +
  44.         MB_ICONINFORMATION);
  45.       return;
  46.     }
  47.     CloseHandle( hThread );
  48.   }
  49.   if ( !InitSocket() )
  50.     return
  51.   while ( !this->Terminated ) 
  52.   {
  53.     YPER_HANDLE_DATA * PerHandleData = NULL;
  54.     len = sizeof(addr);
  55.     AConnect = accept( FListenSock, (SOCKADDR*)&addr, &len );
  56.     if ( AConnect == INVALID_SOCKET )
  57.     {
  58.       SleepEx( 110, false );
  59.       continue;
  60.     }
  61.     PerHandleData=(PPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(YPER_HANDLE_DATA));
  62.     PerHandleData->Sock = AConnect;
  63.     memcpy(&PerHandleData->ClientAddr, &addr, len);
  64.     // 将接受套接字和完成端口关联起来
  65.     CreateIoCompletionPort(
  66.                             (HANDLE)AConnect,
  67.                             FCompletPort,
  68.                             (DWORD)PerHandleData,
  69.                             0
  70.                           );
  71. //    CreateIoCompletionPort( (HANDLE)AConnect, FCompletPort, AConnect, 0 );
  72.     pPerIoDat = NULL;
  73.     pPerIoDat = (PPER_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(YPER_OPERATION_DATA));
  74.     memset( &(pPerIoDat->Overlap), sizeof(OVERLAPPED), 0 );
  75.     memset( pPerIoDat->Buf, BUFFER_SIZE, 0 );
  76.     pPerIoDat->BufData.len = BUFFER_SIZE;
  77.     pPerIoDat->BufData.buf = pPerIoDat->Buf;
  78.     pPerIoDat->OprtType = RECV_POSTED;
  79.     Flags = 0;
  80. //    WSARecv( AConnect, &(pPerIoDat->BufData), 1, BytesRecv, Flags,
  81. //    &(pPerIoDat->Overlap), NULL );
  82.     WSARecv(
  83.                 PerHandleData->Sock,
  84.                 &(pPerIoDat->BufData),
  85.                 1,
  86.                 &BytesRecv,
  87.                 &Flags,
  88.                 (LPWSAOVERLAPPED)&(pPerIoDat->Overlap),
  89.                 NULL
  90.            );
  91.   }
  92.   PostQueuedCompletionStatus( FCompletPort, 0,0,NULL ); 
  93.   CloseHandle( FCompletPort );
  94. }
  95. //---------------------------------------------------------------------------
  96. BOOL __fastcall TListenThread::InitSocket(void)
  97. {
  98.   sockaddr_in addr;
  99.   bool result = False;
  100.   FListenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 
  101.   if ( FListenSock == INVALID_SOCKET )
  102.   {
  103.     MessageBox(0, "Call socket() failed.""Error", MB_OK +
  104.         MB_ICONSTOP);
  105.     return result;
  106.   }
  107.   addr.sin_family = AF_INET;
  108.   addr.sin_port = htons(LISTEN_PORT);
  109.   addr.sin_addr.s_addr = htonl(INADDR_ANY); 
  110.   if ( bind( FListenSock, (const sockaddr *)&addr, sizeof(SOCKADDR) ) == SOCKET_ERROR ) 
  111.   {
  112.     MessageBox(0, "Call bind failed.""Error", MB_OK +
  113.         MB_ICONSTOP);
  114.     return result;
  115.   }
  116.   if ( listen( FListenSock, 5 ) == SOCKET_ERROR ) 
  117.   {
  118.     MessageBox(0, "Call listen failed.""Error", MB_OK +
  119.         MB_ICONSTOP);
  120.     return result;
  121.   }
  122.   result = True;
  123.   return result;
  124. }
  125. //---------------------------------------------------------------------------
  126. DWORD WINAPI WorkerThread(LPVOID CompletPortID)
  127. {
  128.   HANDLE CompletPort ; 
  129.   DWORD CompletKey,BytesTransd,BytesSend,BytesRecv,Flags ;
  130.   PPER_OPERATION_DATA pPerIoDat = NULL;
  131.   PPER_HANDLE_DATA PerHandleData = NULL;
  132. //  LPPER_IO_DATA PerIoData = NULL;
  133.   CompletPort = HANDLE(CompletPortID);
  134.   while (1)
  135.   {
  136.     BytesTransd=0;CompletKey=0;
  137.     GetQueuedCompletionStatus
  138.     (
  139.       CompletPort,
  140.       &BytesTransd,
  141.       (PULONG_PTR)&PerHandleData,
  142.       (LPOVERLAPPED*)(&pPerIoDat),
  143.       /*550*/INFINITE
  144.     );
  145.     if ( ( BytesTransd == 0 ) &
  146.          ( (pPerIoDat==NULL ) || (pPerIoDat->OprtType == RECV_POSTED) ||(pPerIoDat->OprtType == SEND_POSTED) )
  147.        )
  148.     {
  149.       closesocket( CompletKey );
  150.       GlobalFree(PerHandleData);
  151.       GlobalFree(pPerIoDat);
  152.       continue;
  153.     }
  154.     // 数据处理
  155.     // 这儿就收到了来自客户端的数据
  156.     if ( pPerIoDat->OprtType == RECV_POSTED )
  157.     {
  158.       frmMain->ListBox1->Items->Add( pPerIoDat->BufData.buf );
  159.     }
  160.     Flags = 0;
  161.     // 为下一个重叠调用建立单I/O操作数据
  162.     memset( &pPerIoDat->Overlap, sizeof(OVERLAPPED), 0 );
  163.     memset( pPerIoDat->Buf, 4096, 0 );
  164.     pPerIoDat->BufData.len = 4096;
  165.     pPerIoDat->BufData.buf = pPerIoDat->Buf;
  166.     pPerIoDat->OprtType = RECV_POSTED;
  167.     WSARecv( CompletKey, &(pPerIoDat->BufData), 1, &BytesRecv, &Flags,
  168.     (LPWSAOVERLAPPED)&(pPerIoDat->Overlap), NULL );
  169.   }
  170.     //closesocket( CompletKey );
  171.     //Dispose( pPerIoDat );
  172. }
  173. //---------------------------------------------------------------------------
IOCp(I/O Completion Port)是Windows平台上用于高效处理大量I/O操作的一种机制,它特别适合于需要处理大量并发Socket连接的服务器应用程序。通过IOCP,应用程序可以创建一个I/O完成端口,并将I/O对象(如文件句柄或套接字)与之关联,操作系统会将I/O操作的完成情况通知到这个端口。当一个I/O操作完成时,系统会将一个包含结果信息的I/O完成包放入到与IOCP关联的队列中,应用程序可以从中获取完成信息,并执行相应的后续处理。 IOCP的工作流程大致如下: 1. 创建完成端口:使用CreateIoCompletionPort函数创建一个I/O完成端口。 2. 绑定文件句柄:通过CreateIoCompletionPort将网络套接字等I/O句柄与完成端口关联起来。 3. 提交异步I/O操作:应用程序提交异步读写请求到绑定的句柄。 4. 等待完成通知:应用程序调用GetQueuedCompletionStatus函数等待I/O操作的完成通知。 5. 处理完成包:当I/O操作完成时,GetQueuedCompletionStatus会返回,应用程序从返回的数据结构中读取结果,并执行相应的业务逻辑。 使用IOCP的优势在于: - 高效的线程管理:IOCP支持线程池管理,减少了线程创建和销毁的开销。 - 可扩展性:适合处理成千上万的并发连接。 - 高性能:系统自动将I/O完成事件分发到可用的线程,减少了上下文切换和CPU使用率。 IOCP Socket编程适用于需要处理大量并发客户端请求的网络应用,如高性能网络服务器等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值