捐赠 | 广告 | 注册 | 发布精品源码 | 上传 | 关于我们    
  沪ICP备05001939号 DELPHI盒子 | 盒子论坛 | 盒子文章 | 盒子问答悬赏 | 最新更新 | 论坛检索 | 下载中心 | 高级搜索    
  精品专区 | 繁體中文 | 奖励公告栏 | 直通车账号登陆 | 关闭GOOGLE广告 | 临时留言    
盒子资源分类
全部展开 - 全部合拢
【精品源码】 Datasnap iocp framework
关键字:Datasnap iocp framework
来 自:精品
平 台:Win2K/2003/NT/XP 下载所需:80 火柴
深浅度:中级 完成时间:2013/3/12
发布者:soulaw 发布时间:2013/3/12
编辑器:DelphiXE2 语  种:简体中文
分 类:网络 下载浏览:22/20630
加入到我的收藏
下载错误报错
登陆以后才能下载
 用户名:
 密 码:
自动登陆(30天有效)
图片如果打不开,说明流量不够了,请稍候下载……
procedure TIocpTcpSocket.RequestAcceptComplete(PerIoData: PIocpPerIoData);
var
  Connection: TIocpSocketConnection;
  LocalAddrLen, RemoteAddrLen: Integer;
  PLocalAddr, PRemoteAddr: PSockAddr;
begin
  try
    // 将连接放到工作连接列表中
    try
      FConnectionListLocker.Enter;
      Connection := FIdleConnectionList[PerIoData.ClientSocket];
      // 如果之前该连接存在于空闲连接列表中则将它移到工作连接列表中
      if (Connection <> nil) then
      begin
        FConnectionList[PerIoData.ClientSocket] := Connection;
        FIdleConnectionList.Delete(Connection.FSocket);
      end else
      //** 理论上永远不会执行到这里来
      begin
        Connection := FConnectionList[PerIoData.ClientSocket];
        if (Connection = nil) then
        begin
          Connection := AllocConnection(PerIoData.ClientSocket);
          FConnectionList[PerIoData.ClientSocket] := Connection;
        end;
      end;

      // 将Socket邦定到IOCP
      if not AssociateSocketWithCompletionPort(PerIoData.ClientSocket, Connection) then
      begin
        AppendLog('RequestAcceptComplete.AssociateSocketWithCompletionPort failed');
        Connection.Release;
        Exit;
      end;
    finally
      FConnectionListLocker.Leave;
    end;

    Connection.UpdateTick;

    // 对于SO_UPDATE_ACCEPT_CONTEXT,最后一个参数optlen实际需要设定为SizeOf(PAnsiChar)
    // 这一点在MSDN的例子中都是错的!因为经过实际测试发现在64位程序中这里传递SizeOf(PerIoData.ListenSocket)
    // 的话会报错:10014,系统检测到在一个调用中尝试使用指针参数时的无效指针地址。
    // 也就是说这里的optlen实际上应该传递的是一个指针的长度(应该跟内存对齐有关系)
    if (setsockopt(PerIoData.ClientSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
      PAnsiChar(@PerIoData.ListenSocket), SizeOf(PAnsiChar)) = SOCKET_ERROR) then
    begin
      AppendLog('%s.RequestAcceptComplete.setsockopt.SO_UPDATE_ACCEPT_CONTEXT ERROR %d=%s', [ClassName, WSAGetLastError, SysErrorMessage(WSAGetLastError)], ltWarning);
      Connection.Disconnect;
      Exit;
    end;

    // 获取连接地址信息
    GetAcceptExSockaddrs(@PerIoData.Buffer.AcceptExBuffer[0], 0, SizeOf(TAddrBuffer),
      SizeOf(TAddrBuffer), PLocalAddr, LocalAddrLen,
      PRemoteAddr, RemoteAddrLen);

    if not Connection.InitSocket then
    begin
      Connection.Disconnect;
      Exit;
    end;

    // 解析地址信息
    ExtractAddrInfo(PRemoteAddr, RemoteAddrLen, Connection.FRemoteIP, Connection.FRemotePort);

    // 超过最大允许连接数,断开
    if (FMaxClients > 0) and (FConnectionList.Count > FMaxClients) then
    begin
      Connection.Disconnect;
      Exit;
    end;

    if not _TriggerClientConnected(Connection) then Exit;

    // 连接建立之后PostZero读取请求
    if not Connection.PostReadZero then Exit;
  except
    on e: Exception do
      AppendLog('%s.RequestAcceptComplete ERROR %s=%s', [ClassName, e.ClassName, e.Message], ltException);
  end;
end;

procedure TIocpTcpSocket.RequestConnectComplete(Connection: TIocpSocketConnection);
begin
  try
    try
      if not Connection.InitSocket then
      begin
        Connection.Disconnect;
        Exit;
      end;

      try
        FConnectionListLocker.Enter;
        FConnectionList[Connection.FSocket] := Connection;
      finally
        FConnectionListLocker.Leave;
      end;

      Connection.UpdateTick;

      if not _TriggerClientConnected(Connection) then Exit;

      // 连接建立之后PostZero读取请求
      if not Connection.PostReadZero then Exit;
    finally
      Connection.Release; // 对应 AsyncConnect 中的 AddRef;
    end;
  except
    on e: Exception do
      AppendLog('%s.RequestConnectComplete ERROR %s=%s', [ClassName, e.ClassName, e.Message], ltException);
  end;
end;

procedure TIocpTcpSocket.RequestReadZeroComplete(
  Connection: TIocpSocketConnection; PerIoData: PIocpPerIoData);
begin
  try
    try
      if (Connection.IsClosed) then Exit;

      Connection.UpdateTick;

      // 正式开始接收数据
      Connection.PostRead;
    finally
      Connection.Release; // 对应PostReadZero中的AddRef
    end;
  except
    on e: Exception do
      AppendLog('%s.RequestReadZeroComplete ERROR %s=%s', [ClassName, e.ClassName, e.Message], ltException);
  end;
end;

procedure TIocpTcpSocket.RequestReadComplete(Connection: TIocpSocketConnection;
  PerIoData: PIocpPerIoData);
begin
  try
    try
      Connection.DecPendingRecv;

      if (Connection.IsClosed) then Exit;

      if (PerIoData.BytesTransfered = 0) or (PerIoData.Buffer.DataBuf.buf = nil) then
      begin
        Connection.Disconnect;
        Exit;
      end;

      Connection.UpdateTick;

      // PerIoData.Buffer.DataBuf 就是已接收到的数据,PerIoData.BytesTransfered 是实际接收到的字节数
      PerIoData.Buffer.DataBuf.Len := PerIoData.BytesTransfered;

      try
        InterlockedIncrement(FPendingRequest);
        if not _TriggerClientRecvData(Connection, PerIoData.Buffer.DataBuf.buf, PerIoData.Buffer.DataBuf.len) then Exit;
      finally
        InterlockedDecrement(FPendingRequest);
      end;

      // 继续接收客户端数据
      Connection.PostReadZero;
    finally
      Connection.Release; // 对应PostRead中的AddRef
    end;
  except
    on e: Exception do
      AppendLog('%s.RequestReadComplete ERROR %s=%s', [ClassName, e.ClassName, e.Message], ltException);
  end;
end;
Google
 
本站原创作品,未经作者许可,严禁任何方式转载;转载作品,如果侵犯了您的权益,请联系我们
龙脉加密锁 15元起 Grid++Report 报表 申请支付@网
 相关文章
没有相关文章
相关评论
共有评论39条
我要发表评论 查看全部评论
 
  DELPHI盒子版权所有 技术支持:深圳市麟瑞科技有限公司 1999-2024 V4.01 粤ICP备10103342号-1 更新RSS列表