📄 dnudprequests.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 + -