端口复用以及完成端口DEMO(200大洋)(200分)

  • 主题发起人 主题发起人 阿伟~
  • 开始时间 开始时间
好象少了第三和四种情况:
三: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]^ );

   if dwTemp = 0 then //连接已经关闭
   begin
    ......
    continue;
   end else
  begin
   fmMain.ListBox1.Items.Add( FLinks.pBufs[Index]^.buf );
  end;

  //初始化缓冲区
  FLinks.pdwFlags[Index]^ := 0;
  FillChar( FLinks.pOverlaps[Index]^, sizeof(WSAOVERLAPPED), 0 );
  FLinks.pOverlaps[Index]^.hEvent := FLinks.Events[Index];
  FillChar( FLinks.pBufs[Index]^.buf^, BUFFER_SIZE, 0 );

  //递一个接收数据请求
  WSARecv( FLinks.Sockets[Index], FLinks.pBufs[Index], 1, FLinks.pdwRecvd[Index]^, FLinks.pdwFlags[Index]^, FLinks.pOverlaps[Index], nil );
end;
end;
 
刚看了chnplzh给的例子的前2部分,真的很不 错从SOCKET的几代模型都有介绍,真是很好的教材
 
帮顶!

http://www.source520.com

站长开发推广同盟 站长朋友的终极驿站
同时拥有海量源码电子经典书籍下载

http://www.source520.com/search/search.asp

&quot;编程.站长&quot;论坛搜索引擎-----为中国站长注入动力!
 
多人接受答案了。
 
后退
顶部