📄 wsockets.pas
字号:
unit WSockets;
interface
uses
Windows, WinSock, CommandsAndUtils, Classes, Messages;
const
WM_ASYNCSELECT = WM_USER + 1;
READ_BUFFER_SIZE = 1024;
MAX_LOOP = 100;
type
TSocketState = (ssNotStarted, ssClosed, ssConnected, ssListening, ssOpen);
TOnError = procedure(Sender: TObject; Error: integer; Msg: string) of object;
TOnData = procedure(Sender: TObject; Socket: TSocket) of object;
TOnAccept = procedure(Sender: TObject; Socket: TSocket) of object;
TOnConnect = procedure(Sender: TObject; Socket: TSocket) of object;
TOnClose = procedure(Sender: TObject; Socket: TSocket) of object;
TReadBuffer = array[1..READ_BUFFER_SIZE] of byte;
TClientList = class(TObject)
private
FSockets: TList;
protected
function GetSockets(Index: integer): TSocket;
function GetCount: integer;
public
constructor Create;
destructor Destroy; override;
function Add(Socket: TSocket): boolean;
procedure Delete(Socket: TSocket);
procedure Clear;
function IndexOf(Socket: TSocket): integer;
property Sockets[Index: integer]: TSocket read GetSockets; default;
property Count: integer read GetCount;
end;
TCustomWSocket = class(TComponent)
private
{WinSocket Information Private Fields}
FVersion: string;
FDescription: string;
FSystemStatus: string;
FMaxSockets: integer;
FMaxUDPSize: integer;
{End WinSocket Information Private Fields}
FProtocol: integer;
FType: integer;
FReadBuffer: TReadBuffer;
FLocalSocket: TSocket;
FSocketState: TSocketState;
FLastError: integer;
FOnError: TOnError;
protected
procedure SocketError(Error: integer);
function LastErrorDesc: string;
function GetLocalHostAddress: string;
function GetLocalHostName: string;
{Socket Helper Functions}
procedure SocketClose(var Socket: TSocket; Handle: HWND);
function SocketQueueSize(Socket: TSocket): longint;
procedure SocketWrite(Socket: TSocket; Flag: integer; Data: string);
function SocketRead(Socket: TSocket; Flag: integer): string;
function SocketWriteBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
function SocketReadBuffer(Socket: TSocket; Buffer: Pointer; Size, Flag: integer): integer;
procedure SocketWriteTo(Socket: TSocket; Flag: integer; Data: string; var SockAddrIn: TSockAddrIn);
function SocketReadFrom(Socket: TSocket; Flag: integer; var SockAddrIn: TSockAddrIn): string;
function SocketWriteBufferTo(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
function SocketReadBufferFrom(Socket: TSocket; Buffer: Pointer; Size, Flag: integer; var SockAddrIn: TSockAddrIn): integer;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{Address and Port Resolving Helper Functions}
function GetSockAddrIn(Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
function GetAnySockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
function GetBroadcastSockAddrIn(Port: string; var SockAddrIn: TSockAddrIn): boolean;
function SockAddrInToName(SockAddrIn: TSockAddrIn): string;
function SockAddrInToAddress(SockAddrIn: TSockAddrIn): string;
function SockAddrInToPort(SockAddrIn: TSockAddrIn): string;
function SocketToName(Socket: TSocket): string;
function SocketToAddress(Socket: TSocket): string;
function SocketToPort(Socket: TSocket): string;
function PeerToName(Socket: TSocket): string;
function PeerToAddress(Socket: TSocket): string;
function PeerToPort(Socket: TSocket): string;
{WinSocket Information Properties}
property Version: string read FVersion;
property Description: string read FDescription;
property SystemStatus: string read FSystemStatus;
property MaxSockets: integer read FMaxSockets;
property MaxUDPSize: integer read FMaxUDPSize;
{End WinSocket Information Properties}
property LocalSocket: TSocket read FLocalSocket;
property SocketState: TSocketState read FSocketState;
property LastError: integer read FLastError;
property LocalHostAddress: string read GetLocalHostAddress;
property LocalHostName: string read GetLocalHostName;
published
property OnError: TOnError read FOnError write FOnError;
end;
TTCPClient = class(TCustomWSocket)
private
FHandle: HWND;
FHost: string;
FPort: string;
FOnData: TOnData;
FOnConnect: TOnConnect;
FOnClose: TOnClose;
protected
procedure WndProc(var AMsg: TMessage);
procedure OpenConnection(Socket: TSocket; Error: word);
procedure IncommingData(Socket: TSocket; Error: word);
procedure CloseConnection(Socket: TSocket; Error: word);
function GetPeerAddress: string;
function GetPeerPort: string;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Open;
procedure Close;
function Peek: string;
procedure Write(Data: string);
function Read: string;
function WriteBuffer(Buffer: Pointer; Size: integer): integer;
function ReadBuffer(Buffer: Pointer; Size: integer): integer;
property Handle: HWND read FHandle;
property PeerAddress: string read GetPeerAddress;
property PeerPort: string read GetPeerPort;
published
property Host: string read FHost write FHost;
property Port: string read FPort write FPort;
property OnData: TOnData read FOnData write FOnData;
property OnConnect: TOnConnect read FOnConnect write FOnConnect;
property OnClose: TOnClose read FOnClose write FOnClose;
end;
TTCPServer = class(TCustomWSocket)
private
FHandle: HWND;
FPort: string;
FOnData: TOnData;
FOnAccept: TOnAccept;
FOnClose: TOnClose;
FClients: TClientList;
protected
procedure WndProc(var AMsg: TMessage);
procedure OpenConnection(Socket: TSocket; Error: word);
procedure IncommingData(Socket: TSocket; Error: word);
procedure CloseConnection(Socket: TSocket; Error: word);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Open;
procedure Close;
function Peek(Socket: TSocket): string;
procedure Write(Socket: TSocket; Data: string);
function Read(Socket: TSocket): string;
function WriteBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
function ReadBuffer(Socket: TSocket; Buffer: Pointer; Size: integer): integer;
procedure Disconnect(Socket: TSocket);
property Handle: HWND read FHandle;
property Clients: TClientList read FClients;
published
property Port: string read FPort write FPort;
property OnData: TOnData read FOnData write FOnData;
property OnAccept: TOnAccept read FOnAccept write FOnAccept;
property OnClose: TOnClose read FOnClose write FOnClose;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TTCPClient, TTCPServer]);
end;
(**** TClientList Class ****)
constructor TClientList.Create;
begin
inherited Create;
FSockets:= TList.Create;
end;
destructor TClientList.Destroy;
begin
Clear;
FSockets.Free;
inherited Destroy;
end;
function TClientList.GetSockets(Index: integer): TSocket;
begin
Result:= TSocket(FSockets[Index]);
end;
function TClientList.GetCount: integer;
begin
Result:= FSockets.Count;
end;
function TClientList.Add(Socket: TSocket): boolean;
begin
Result:= (FSockets.Add(Ptr(Socket)) >= 0);
end;
procedure TClientList.Delete(Socket: TSocket);
var
i: integer;
begin
for i:= 0 to FSockets.Count-1 do
begin
if TSocket(FSockets[i]) = Socket then
begin
FSockets.Delete(i);
Break;
end;
end;
end;
procedure TClientList.Clear;
begin
FSockets.Clear;
end;
function TClientList.IndexOf(Socket: TSocket): integer;
var
i: integer;
begin
Result:= -1;
for i:= 0 to FSockets.Count-1 do
begin
if TSocket(FSockets[i]) = Socket then
begin
Result:= i;
Break;
end;
end;
end;
(**** TCustomWSocket Class ****)
constructor TCustomWSocket.Create(AOwner: TComponent);
var
WSAData: TWSAData;
begin
inherited Create(AOwner);
FProtocol:= IPPROTO_IP;
FType:= SOCK_RAW;
FLocalSocket:= INVALID_SOCKET;
FSocketState:= ssNotStarted;
FLastError:= WSAStartup($101, WSAData);
if FLastError = 0 then
begin
FSocketState:= ssClosed;
with WSAData do
begin
FVersion:= Concat(IntToStr(Hi(wVersion)),'.',(IntToStr(Lo(wVersion))));
FDescription:= StrPas(szDescription);
FSystemStatus:= StrPas(szSystemStatus);
FMaxSockets:= iMaxSockets;
FMaxUDPSize:= iMaxUDPDg;
end;
end
else
SocketError(FLastError);
end;
destructor TCustomWSocket.Destroy;
begin
if FLocalSocket <> INVALID_SOCKET then
closesocket(FLocalSocket);
if FSocketState <> ssNotStarted then
if WSACleanUp = SOCKET_ERROR then
SocketError(WSAGetLastError);
inherited Destroy;
end;
function TCustomWSocket.GetSockAddrIn(
Host, Port: string; var SockAddrIn: TSockAddrIn): boolean;
var
ProtoEnt: PProtoEnt;
ServEnt: PServEnt;
HostEnt: PHostEnt;
begin
Result:= false;
SockAddrIn.sin_family:= AF_INET;
ProtoEnt:= getprotobynumber(FProtocol);
if ProtoEnt = nil then
begin
SocketError(WSAGetLastError);
Exit;
end;
ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
if ServEnt = nil then
SockAddrIn.sin_port:= htons(StrToInt(Port))
else
SockAddrIn.sin_port:= ServEnt^.s_port;
SockAddrIn.sin_addr.s_addr:= inet_addr(PChar(Host));
if SockAddrIn.sin_addr.s_addr = INADDR_NONE then
begin
HostEnt:= gethostbyname(PChar(Host));
if HostEnt = nil then
begin
SocketError(WSAGetLastError);
Exit;
end;
SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^);
end;
Result:= true;
end;
function TCustomWSocket.GetAnySockAddrIn(
Port: string; var SockAddrIn: TSockAddrIn): boolean;
var
ProtoEnt: PProtoEnt;
ServEnt: PServEnt;
begin
Result:= false;
SockAddrIn.sin_family:= AF_INET;
ProtoEnt:= getprotobynumber(FProtocol);
if ProtoEnt = nil then
Exit;
ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
if ServEnt = nil then
SockAddrIn.sin_port:= htons(StrToInt(Port))
else
SockAddrIn.sin_port:= ServEnt^.s_port;
SockAddrIn.sin_addr.s_addr:= INADDR_ANY;
Result:= true;
end;
function TCustomWSocket.GetBroadcastSockAddrIn(
Port: string; var SockAddrIn: TSockAddrIn): boolean;
var
ProtoEnt: PProtoEnt;
ServEnt: PServEnt;
begin
Result:= false;
SockAddrIn.sin_family:= AF_INET;
ProtoEnt:= getprotobynumber(FProtocol);
if ProtoEnt = nil then
Exit;
ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name);
if ServEnt = nil then
SockAddrIn.sin_port:= htons(StrToInt(Port))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -