最近使用delphi编写iocp服务器,使用线程池和socket池,在使用AcceptEx函数时,用WSAIoctl加载时,出现了不顺利,有做过的请指教一下。谢谢!最好能亮出代码,不甚感激!1服务器socketiocp线程池

解决方案 »

  1.   

    情况是这样的:我用WSAIoctl 加载了AcceptEx函数到内存。我是这样定义的guid:
    WSAID_ACCEPTEX:TGUID = (D1: $B5367DF1; D2: $CBAC; D3: $11CF; D4: ($95, $CA, $00, $80, $5F, $48, $A1,$92));
    调用wsaioctl,成功。然后,用10 socket 发送了10个AcceptEx,方法去接受新连接。并把10个socket绑定到了完成端口上(用BindIoCompletionCallback绑定的)。也成功了。可是我在客户端连接服务端,并发送数据。服务端没有任何反应。
    代码:
    Log('服务器正在启动...',[]);
      //创建socket
      FListenSock := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nil, 0, WSA_FLAG_OVERLAPPED);
      if FListenSock = INVALID_SOCKET then
      begin
        ErrorLog('创建套接字错误:%d', [WSAGetLastError]);
        exit;
      end;
      //设定地址和端口
      ListenAddr.sin_family := AF_INET;
      ListenAddr.sin_port := htons(FLocalPort);
      if FLocalAddr = '' then
        ListenAddr.sin_addr.S_addr := INADDR_ANY
      else
        ListenAddr.sin_addr.S_addr := inet_addr(pAnsichar(FLocalAddr));//一定要转化成pcahr
      //绑定
      if Bind(FListenSock, TSockAddr(ListenAddr),sizeof(ListenAddr)) <> 0 then
      begin
        ErrorLog('绑定套接字错误:%d', [WSAGetLastError]);
        //closeSocket(FListenSocket);
        exit;
      end;
      //监听
      if listen(FListenSock, SOMAXCONN) <> 0 then
      begin
        ErrorLog('监听套接字错误:%d', [WSAGetLastError]);
        //closeSocket(FListenSocket);
        exit;
      end;  Log('创建连接池....',[]);
      
      //初始化socket池锁和等待接受socket数量
      FSockListLock := TCriticalSection.Create;
      FAcceptSockCount := 0;  //加载sock2 Ex方法到内存
      FAcceptEx := nil;
      FDisconnectEx := nil;
      //LoadExFunc(FListenSock,efAcceptEx,@@FAcceptEx);
      //LoadExFunc(FListenSock,efDisconnectEx,@@FDisconnectEx);  FSockList := TList.Create;
      //发出1000个接受socket
      for i := 1 to 10 do
      begin
        //生成socket
        AccSock := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nil, 0, WSA_FLAG_OVERLAPPED);
        if AccSock = INVALID_SOCKET then
        begin
          ErrorLog('创建连接池错误:%d', [WSAGetLastError]);
          //closeSocket(FListenSocket);
          //closeAllExitsSocket
          exit;
        end;
        
        //创建overlapped数据结构
        new(olData);
        olData^.Statu := cbaAccept;
        olData^.wsaBuffer.buf := olData^.Buffer;
        olData^.wsaBuffer.len := BUFFER_SIZE;
        
        //把socket绑定到完成端口
        rt := BindIoCompletionCallback(AccSock,@DealAction,0);    //发送异步接受请求
        if FAcceptEx(FListenSock,AccSock,olData^.wsaBuffer.buf,256,256,256,
          @dwBytes,Poverlapped(olData)) then
        begin
          closesocket(Accsock);
        end;
        
        //维护sock列表和接受新链接的sock数量
        FSockList.Add(@AccSock);
        inc(FacceptSockCount);
      

  2.   

    这是我的加载winsock2 函数的方法
    function LoadExFunc(sk:TSocket;fuc:TExFunc;pfun:Pointer):string;
    var
      dwBytes:DWORD;
    begin
      result := 'OK';
      dwBytes := 0;
      if sk = INVALID_SOCKET then
      begin
        sk := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nil, 0, WSA_FLAG_OVERLAPPED);
        if sk=INVALID_SOCKET then
        begin
          result := format('加载扩展函数时创建套接字失败,错误号:%d',[WSAGetLastError]);
          exit;
        end;
      end;
      case fuc of
        efAcceptEx:
          begin
             if SOCKET_ERROR = WSAIoctl(sk,SIO_GET_EXTENSION_FUNCTION_POINTER,
               @WSAID_ACCEPTEX,sizeof(WSAID_ACCEPTEX),pfun,sizeof(pfun),dwBytes,nil,nil) then
              begin
                result := format('加载扩展函数AcceptEx失败,错误号:%d',[WSAGetLastError]);
                exit;
              end;
          end;
        efDisconnectEx:
          begin
            if SOCKET_ERROR = WSAIoctl(sk,SIO_GET_EXTENSION_FUNCTION_POINTER,
               @WSAID_DISCONNECTEX,sizeof(WSAID_DISCONNECTEX),@pfun,sizeof(pfun),dwBytes,nil,nil) then
              begin
                result := format('加载扩展函数DisconnectEx失败,错误号:%d',[WSAGetLastError]);
                exit;
              end;
          end;
      end;
    end;