if SOCKET_ERROR=WSAAsyncSelect(sock, Handle,WM_SOCKET,FD_READ) then
      Exit;
正常情况下可以
写成window服务时 Handle 如何设置请教!!!

解决方案 »

  1.   

    服务程序中也可以动态创建一个窗口,用这个窗口来接收和处理socket消息
      

  2.   

    不过还是建议楼主不要用WSAAsyncSelect,这个模型本来就是针对窗口程序而设计的,必须通过窗口消息来处理网络事件,你可以用WSAEventSelect嘛,它就适用于非窗口程序。
      

  3.   

    你可以生成一个大小为0窗口就好了,使用AllocateHWnd 函数
      

  4.   

    請了解一下基于Delphi的Socket I/O模型全接触,WSAEventSelect模型: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; 
      

  5.   

    2.上面使用的是基於WSAEventSelect I/O線程,以下Overlapped I/O 事件通知模型,供LZ參考之: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; 
      

  6.   

    WSAEventSelect模型的不足之处是:每个WSAEventSelect模型最多只能管理64个套接字。
    当应用程序中需要管理多余64个套接字时,就需要额外创建线程
      

  7.   

    一个基于消息 一个基于事件
    我倒建议用消息的WSAAsyncSelect模型