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

📄 dnudprequests.pas

📁 一个国外比较早的IOCP控件
💻 PAS
字号:
// The contents of this file are used with permission, subject to
// the Mozilla Public License Version 1.1 (the "License"); you may
// not use this file except in compliance with the License. You may
// obtain a copy of the License at
// http://www.mozilla.org/MPL/MPL-1.1.html
//
// Software distributed under the License is distributed on an
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
// implied. See the License for the specific language governing
// rights and limitations under the License.
unit DnUdpRequests;
interface
uses
  Classes, Windows, SysUtils, WinSock2,
  DnRtl, DnConst, DnUdpReactor, DnInterfaces;

type
  IDnUdpReadHandler = interface
    procedure DoRead(ThreadContext: TDnThreadContext; Socket: IDnUdpSocket; Key: Pointer; FromAddr: String; Buffer: PChar; BufSize: Cardinal);
    procedure DoReadError(ThreadContext: TDnThreadContext; Socket: IDnUdpSocket;
      Key: Pointer; ErrorCode: Cardinal);
  end;
  
  TDnUdpReadRequest = class(TDnUdpRequest)
  protected
    FFromAddr:    TSockAddr;
    FFromAddrLen: Cardinal;
    FWasRead:     Cardinal;
    FFlags:       Cardinal;
    FHandler:     IDnUdpReadHandler;
    FStrBuffer:   String;
    
    procedure Execute; override;
    procedure CallHandler(ThrContext: TDnThreadContext); override;
    procedure ReExecute; override;
    function  RequestType: TDnIORequestType; override;
    function  IsCPUNeeded: Boolean; override;
    procedure SetTransferred(Transferred: Cardinal); override;
  public
    constructor Create(Socket: IDnUdpSocket; Key: Pointer;
      Handler: IDnUdpReadHandler; Buffer: PChar; BufSize: Cardinal); overload;
    constructor CreateString(Socket: IDnUdpSocket; Key: Pointer;
      Handler: IDnUdpReadHandler; Buffer: String); overload;

    destructor Destroy; override;
  end;

  IDnUdpWriteHandler = interface
    procedure DoWrite(ThreadContext: TDnThreadContext; Socket: IDnUdpSocket; Key: Pointer; Buffer: PChar; BufSize: Cardinal);
    procedure DoWriteError(ThreadContext: TDnThreadContext; Socket: IDnUdpSocket; Key: Pointer; ErrorCode: Cardinal);
  end;

  TDnUdpWriteRequest = class(TDnUdpRequest)
  protected
    FSockAddr: TSockAddr;
    FWasWritten: Cardinal;
    FStrBuffer: String;
    FBuffer: PChar;
    FBufSize: Cardinal;
    FHandler: IDnUdpWriteHandler;
    
    procedure Execute; override;
    procedure CallHandler(ThrContext: TDnThreadContext); override;
    procedure InitWriteRequest(const ToAddr: String; Port: Word);
    procedure ReExecute; override;
    function  RequestType: TDnIORequestType; override;
    function  IsCPUNeeded: Boolean; override;
    procedure SetTransferred(Transferred: Cardinal); override;
  public
    constructor Create(Socket: IDnUdpSocket; Key: Pointer;
      Handler: IDnUdpWriteHandler; Buffer: PChar; BufSize: Cardinal;
      const ToAddr: String; Port: Word);
    constructor CreateString(Socket: IDnUdpSocket; Key: Pointer;
      Handler: IDnUdpWriteHandler; Buffer: String;
      const ToAddr: String; Port: Word);
    destructor Destroy; override;
  end;

implementation

constructor TDnUdpReadRequest.Create(Socket: IDnUdpSocket; Key: Pointer;
  Handler: IDnUdpReadHandler; Buffer: PChar; BufSize: Cardinal);
begin
  inherited Create(Socket, Key);
  FWSABuf.len := BufSize;
  FWSABuf.buf := Buffer;
  FWasRead := 0;
  FBuffer := Buffer;
  FBufSize := BufSize;
  FHandler := Handler;
end;

constructor TDnUdpReadRequest.CreateString(Socket: IDnUdpSocket; Key: Pointer;
  Handler: IDnUdpReadHandler; Buffer: String);
begin
  inherited Create(Socket, Key);
  FWSABuf.len := Length(Buffer);
  FWSABuf.buf := @Buffer[1];
  FWasRead := 0;
  FBuffer := @Buffer[1];
  FBufSize := Length(Buffer);
  FHandler := Handler;
  FStrBuffer := Buffer;
end;

destructor TDnUdpReadRequest.Destroy;
begin
  inherited Destroy;
end;

procedure TDnUdpReadRequest.Execute;
var SockImpl: TDnUdpSocket;
    ResCode: Integer;
begin
  SockImpl := TDnUdpSocket.CheckImpl(FSocket);
  FFromAddrLen := SizeOf(FFromAddr);
  FFlags := 0;
  InterlockedIncrement(PendingRequests);
  ResCode := WinSock2.WSARecvFrom(SockImpl.SocketHandle, @FWSABuf, 1, FWasRead, FFlags, @FFromAddr,
    @FFromAddrLen, @FContext.Overlapped, Nil);

  if ResCode <> 0 then
  begin
    ResCode := WSAGetLastError;
    if ResCode <> WSA_IO_PENDING then
      PostError();
  end;
end;

procedure TDnUdpReadRequest.CallHandler(ThrContext: TDnThreadContext);
begin
  if FErrorCode = 0 then
    FHandler.DoRead(ThrContext, FSocket, FKey, StrPas(WinSock2.inet_ntoa(FFromAddr.sin_addr)), FBuffer, FWasRead)
  else
    FHandler.DoReadError(ThrContext, FSocket, FKey, FErrorCode);
end;

procedure TDnUdpReadRequest.ReExecute;
begin
  Execute;
end;

function  TDnUdpReadRequest.RequestType: TDnIORequestType;
begin
  Result := rtRead;
end;

function  TDnUdpReadRequest.IsCPUNeeded: Boolean;
begin
  Result := False;
end;

procedure TDnUdpReadRequest.SetTransferred(Transferred: Cardinal);
begin
  Inc(FWasRead, Transferred);
end;

//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

procedure TDnUdpWriteRequest.InitWriteRequest(const ToAddr: String; Port: Word);
begin
  FillChar(FSockAddr, sizeof(FSockAddr), 0);
  FSockAddr.sin_family := AF_INET;
  FSockAddr.sin_port := Winsock2.htons(Port);
  FSockAddr.sin_addr.S_addr := Winsock2.inet_addr(PChar(ToAddr));
end;

constructor TDnUdpWriteRequest.Create(Socket: IDnUdpSocket; Key: Pointer;
  Handler: IDnUdpWriteHandler; Buffer: PChar; BufSize: Cardinal;
  const ToAddr: String; Port: Word);
begin
  inherited Create(Socket, Key);
  FWSABuf.len := BufSize;
  FWSABuf.buf := Buffer;
  FWasWritten := 0;
  FBuffer := Buffer;
  FBufSize := BufSize;
  FHandler := Handler;
  InitWriteRequest(ToAddr, Port);
end;

constructor TDnUdpWriteRequest.CreateString(Socket: IDnUdpSocket; Key: Pointer;
  Handler: IDnUdpWriteHandler; Buffer: String;
  const ToAddr: String; Port: Word);
begin
  inherited Create(Socket, Key);
  FWSABuf.len := Length(Buffer);
  FWSABuf.buf := @Buffer[1];
  FWasWritten := 0;
  FBuffer := @Buffer[1];
  FBufSize := Length(Buffer);
  FStrBuffer := Buffer;
  FHandler := Handler;
  InitWriteRequest(ToAddr, Port);
end;

destructor TDnUdpWriteRequest.Destroy;
begin
  inherited Destroy;
end;

procedure TDnUdpWriteRequest.Execute;
var SockImpl: TDnUdpSocket;
    ResCode: Integer;
begin
  SockImpl := TDnUdpSocket.CheckImpl(FSocket);
  InterlockedIncrement(PendingRequests);
  ResCode := WinSock2.WSASendTo(SockImpl.SocketHandle, @FWSABuf, 1, FWasWritten,
    0, @FSockAddr,  sizeof(FSockAddr), @FContext.Overlapped, Nil);
  if ResCode <> 0 then
  begin
    ResCode := WSAGetLastError;
    if ResCode <> WSA_IO_PENDING then
      PostError();
  end;
end;

procedure TDnUdpWriteRequest.CallHandler(ThrContext: TDnThreadContext);
begin
  if FErrorCode = 0 then
    FHandler.DoWrite(ThrContext, FSocket, FKey, FBuffer, FWasWritten)
  else
    FHandler.DoWriteError(ThrContext, FSocket, FKey, FErrorCode);
end;

procedure TDnUdpWriteRequest.ReExecute;
begin
  Execute;
end;

function  TDnUdpWriteRequest.RequestType: TDnIORequestType;
begin
  Result := rtWrite;
end;

function  TDnUdpWriteRequest.IsCPUNeeded: Boolean;
begin
  Result := False;
end;

procedure TDnUdpWriteRequest.SetTransferred(Transferred: Cardinal);
begin
  Inc(FWasWritten, Transferred);
end;

end.

⌨️ 快捷键说明

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