⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udiclientcontext.pas

📁 楠楠写的DBiocp例子都是源码
💻 PAS
字号:
unit uDIClientContext;



interface

uses
  Windows, SysUtils, WinSock2, uCriticalSection, uDIBuffer, uCircularBuffer, uDIProtocol;

type
  //心跳结构
  PTHeartBeatParam = ^THeartBeatParam;
  THeartBeatParam = packed record
    m_BeginTime: DWORD;                             //心跳时间
  end;

  //per-Handle
  TDIClientContext = Class
  public
    m_pNext:              TDIClientContext;         //指向下一个DIClientChannel
    m_Socket:             TSocket;                  //绑定完成端口
    m_CloseOverlap:       OVERLAPPED;               //重叠结构投递CloseSocket时用
    m_KeyID:              Word;                     //客户端标识
    FLocalAddr:           PSockAddr;                //连接的本地地址
    FRemoteAddr:          PSockAddr;                //连接的远程地址

    m_nOutOfPendRecvIO:	      DWORD;                //套节字上抛出的Recv数量
    m_nOutOfPendSendIO:       DWORD;                //套节字上抛出的Send数量
    m_nOutOfPendCloseSocket:  DWORD;                //套节字上抛出的CloseSocket数量
    m_nOutOfPendIO:           DWORD;                //IOCP未决的I/O总数
  private
    m_HeartBeatParam:     THeartBeatParam;          //心跳结构
    m_SendSequenceNumber: DWORD;                    //下一个发送序列号
    m_ReadSequenceNumber: DWORD;                    //下一个接收序列号
    m_CurrentSendSequenceNumber: DWORD;             //当前发送序列号
    m_CurrentReadSequenceNumber: DWORD;             //当前接收序列号
  private
    sRemoteIP:            String;                   //IP客户端
    m_bClosed:            Boolean;                  //该套接字是否被关闭
    m_bPostCloseSocket:   Boolean;                  //是否已经投递了关闭套接字的I/O

    FRecvBuffer:          TDIBuffer;                //接收缓冲区
    FSendBuffer:          TDIBuffer;                //发送缓冲区
    FOutOfOrderBuffer:    TDIBuffer;                //记录没有按顺序完成的读I/O
    //FRecvCircularBuffer:  TCircularBuffer;        //接收环形Buffer区
    //FSendCircularBuffer:  TCircularBuffer;        //发送环形Buffer区
    m_ContextLock:        TCriticalSection;         //临界
  public
    procedure EnterIOLoop(m_Op: IOEventType);
    procedure ExitIOLoop(m_Op: IOEventType);
    procedure SetHeartBeatParam(Time: DWORD);
    procedure SetupOvlpClose;                      //该上下文是否还有未决的I/O
    function IsOutOfPendIO(var nSend, nRecv, nClosed: Integer): Boolean;  
  published
    property FClosed: Boolean read m_bClosed write m_bClosed;
    property FPostCloseSocket: Boolean read m_bPostCloseSocket write m_bPostCloseSocket;
    property FSocket: TSocket read m_socket write m_socket;
    property FContextLock: TCriticalSection read m_ContextLock write m_ContextLock;
    property RecvBuffer: TDIBuffer read FRecvBuffer write FRecvBuffer;
    property SendBuffer: TDIBuffer read FSendBuffer write FSendBuffer;
    //property RecvCircularBuffer: TCircularBuffer read FRecvCircularBuffer write FRecvCircularBuffer;
    //property SendCircularBuffer: TCircularBuffer read FSendCircularBuffer write FSendCircularBuffer;
    property FHeartBeatParam: THeartBeatParam read m_HeartBeatParam write m_HeartBeatParam;
    property FRemoteIP: string read sRemoteIP write sRemoteIP;
    property FCloseOverlap: OVERLAPPED read m_CloseOverlap;
  public
    procedure InitClientContext;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

constructor TDIClientContext.Create;
begin
  inherited Create;
  m_ContextLock := TCriticalSection.Create;
  FOutOfOrderBuffer := nil;
  FRecvBuffer := TDIBuffer.Create;
  FSendBuffer := TDIBuffer.Create;
  //FRecvCircularBuffer := TCircularBuffer.Create(RECV_CIRCULAR_BUFFER_SIZE);
  //FSendCircularBuffer := TCircularBuffer.Create(SEND_CIRCULAR_BUFFER_SIZE);
  InitClientContext;
end;

procedure TDIClientContext.InitClientContext;
begin
  m_Socket := INVALID_SOCKET;
  m_bClosed := FALSE;
  m_bPostCloseSocket := FALSE;
  m_KeyID := 0;
  m_pNext := nil;
  m_nOutOfPendRecvIO := 0;
  m_nOutOfPendSendIO := 0;
  m_nOutOfPendCloseSocket := 0;
  m_nOutOfPendIO := 0;

  m_SendSequenceNumber := 0;
  m_ReadSequenceNumber := 0;
  m_CurrentSendSequenceNumber := 0;
  m_CurrentReadSequenceNumber := 0;

  m_HeartBeatParam.m_BeginTime := 0;
  sRemoteIP := '';

  FRecvBuffer.InitBuffer;
  FSendBuffer.InitBuffer;
  //FRecvCircularBuffer.SetEmpty;
  //FSendCircularBuffer.SetEmpty;
end;

procedure TDIClientContext.SetupOvlpClose;
begin
  ZeroMemory(@m_CloseOverlap, SizeOf(m_CloseOverlap));
  m_CloseOverlap.Offset := DWord(IOWSACloseSocket);
end;

destructor TDIClientContext.Destroy;
begin
  FreeAndNil(FRecvBuffer);
  FreeAndNil(FSendBuffer);
  //FreeAndNil(FRecvCircularBuffer);
  //FreeAndNil(FSendCircularBuffer);
  FreeAndNil(m_ContextLock);
  inherited Destroy;
end;

procedure TDIClientContext.EnterIOLoop(m_Op: IOEventType);
begin
  case m_Op of
    IOWSARecv:
      Inc(m_nOutOfPendRecvIO);
    IOWSASend:
      Inc(m_nOutOfPendSendIO);
    IOWSACloseSocket:
      Inc(m_nOutOfPendCloseSocket);
  end;
  m_nOutOfPendIO := m_nOutOfPendRecvIO + m_nOutOfPendSendIO + m_nOutOfPendCloseSocket;
end;

procedure TDIClientContext.ExitIOLoop(m_Op: IOEventType);
begin
  case m_Op of
    IOWSARecv:
      Dec(m_nOutOfPendRecvIO);
    IOWSASend:
      Dec(m_nOutOfPendSendIO);
    IOWSACloseSocket:
      Dec(m_nOutOfPendCloseSocket);
  end;
  m_nOutOfPendIO := m_nOutOfPendRecvIO + m_nOutOfPendSendIO + m_nOutOfPendCloseSocket;
end;

function TDIClientContext.IsOutOfPendIO(var nSend, nRecv, nClosed: Integer): Boolean;
begin
  Result := m_nOutOfPendIO = 0;
  nSend := m_nOutOfPendSendIO;
  nRecv := m_nOutOfPendRecvIO;
  nClosed := m_nOutOfPendCloseSocket;
end;

procedure TDIClientContext.SetHeartBeatParam(Time: DWORD);
begin
  m_HeartBeatParam.m_BeginTime := Time;
end;


end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -