📄 idstacklinux.pas
字号:
function TIdStackLinux.WSSendTo(ASocket: TIdStackSocketHandle;
var ABuffer; const ABufferLength, AFlags: Integer; const AIP: string;
const APort: integer): Integer;
var
Addr: SockAddr;
begin
FillChar(Addr, SizeOf(Addr), 0);
with Addr do
begin
sin_family := Id_PF_INET;
TranslateStringToTInAddr(AIP, sin_addr);
sin_port := HToNs(APort);
end;
Result := SendTo(ASocket, ABuffer, ABufferLength, AFlags or Id_MSG_NOSIGNAL, Addr, SizeOf(Addr));
end;
function TIdStackLinux.WSSetSockOpt(ASocket: TIdStackSocketHandle;
ALevel, AOptName: Integer; AOptVal: PChar; AOptLen: Integer): Integer;
begin
Result := SetSockOpt(ASocket, ALevel, AOptName, AOptVal, AOptLen);
end;
function TIdStackLinux.WSGetLastError: Integer;
begin
Result := System.GetLastError;
if Result = Id_WSAEPIPE then
begin
Result := Id_WSAECONNRESET;
end;
end;
function TIdStackLinux.WSSocket(AFamily, AStruct, AProtocol: Integer): TIdStackSocketHandle;
begin
Result := Socket(AFamily, AStruct, AProtocol);
end;
function TIdStackLinux.WSHToNs(AHostShort: Word): Word;
begin
Result := HToNs(AHostShort);
end;
function TIdStackLinux.WSNToHs(ANetShort: Word): Word;
begin
Result := NToHs(ANetShort);
end;
function TIdStackLinux.WSGetLocalAddresses: TStrings;
begin
if FLocalAddresses = nil then
begin
FLocalAddresses := TStringList.Create;
end;
PopulateLocalAddresses;
Result := FLocalAddresses;
end;
function TIdStackLinux.WSGetServByName(const AServiceName: string): Integer;
var
ps: PServEnt;
begin
ps := GetServByName(PChar(AServiceName), nil);
if ps <> nil then begin
Result := Ntohs(ps^.s_port);
end else begin
try
Result := StrToInt(AServiceName);
except
on EConvertError do raise EIdInvalidServiceName.CreateFmt(RSInvalidServiceName, [AServiceName]);
end;
end;
end;
function TIdStackLinux.WSGetServByPort(const APortNumber: Integer): TStrings;
var
ps: PServEnt;
i: integer;
p: array of PChar;
begin
Result := TStringList.Create;
p := nil;
try
ps := GetServByPort(HToNs(APortNumber), nil);
if ps <> nil then
begin
Result.Add(ps^.s_name);
i := 0;
p := pointer(ps^.s_aliases);
while p[i] <> nil do
begin
Result.Add(PChar(p[i]));
inc(i);
end;
end;
except
Result.Free;
end;
end;
function TIdStackLinux.WSHToNL(AHostLong: LongWord): LongWord;
begin
Result := HToNL(AHostLong);
end;
function TIdStackLinux.WSNToHL(ANetLong: LongWord): LongWord;
begin
Result := NToHL(ANetLong);
end;
procedure TIdStackLinux.PopulateLocalAddresses;
type
TaPInAddr = Array[0..250] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
i: integer;
AHost: PHostEnt;
PAdrPtr: PaPInAddr;
begin
FLocalAddresses.Clear ;
AHost := GetHostByName(PChar(WSGetHostName));
if AHost = nil then
begin
CheckForSocketError(SOCKET_ERROR);
end
else
begin
PAdrPtr := PAPInAddr(AHost^.h_addr_list);
i := 0;
while PAdrPtr^[i] <> nil do
begin
FLocalAddresses.Add(TInAddrToString(PAdrPtr^[I]^));
Inc(I);
end;
end;
end;
function TIdStackLinux.WSGetLocalAddress: string;
begin
Result := LocalAddresses[0];
end;
procedure TIdStackLinux.TranslateStringToTInAddr(AIP: string; var AInAddr);
begin
with TInAddr(AInAddr).S_un_b do
begin
if not GetIPInfo(AIP, @s_b1, @s_b2, @s_b3, @s_b4) then
begin
raise EIdInvalidIPAddress.CreateFmt(RSStackInvalidIP, [AIP]);
end;
end;
end;
function TIdStackLinux.WSGetHostByAddr(const AAddress: string): string;
//GetHostByAddr is thread-safe in Linux. It might not be safe in Solorus or BSD Unix
var
Host: PHostEnt;
LAddr: u_long;
begin
LAddr := inet_addr(PChar(AAddress));
Host := GetHostByAddr(@LAddr,SizeOf(LAddr),AF_INET);
if (Host <> nil) then
begin
Result := Host^.h_name;
end
else
begin
RaiseSocketError(h_errno);
end;
end;
function TIdStackLinux.WSShutdown(ASocket: TIdStackSocketHandle; AHow: Integer): Integer;
begin
Result := Shutdown(ASocket, AHow);
end;
procedure TIdStackLinux.WSGetPeerName(ASocket: TIdStackSocketHandle;
var VFamily: Integer; var VIP: string; var VPort: Integer);
var
i: Cardinal;
LAddr: TSockAddrIn;
begin
i := SizeOf(LAddr);
CheckForSocketError(GetPeerName(ASocket, LAddr, i));
VFamily := LAddr.sin_family;
VIP := TInAddrToString(LAddr.sin_addr);
VPort := Ntohs(LAddr.sin_port);
end;
procedure TIdStackLinux.WSGetSockName(ASocket: TIdStackSocketHandle;
var VFamily: Integer; var VIP: string; var VPort: Integer);
var
i: Cardinal;
LAddr: TSockAddrIn;
begin
i := SizeOf(LAddr);
CheckForSocketError(GetSockName(ASocket, LAddr, i));
VFamily := LAddr.sin_family;
VIP := TInAddrToString(LAddr.sin_addr);
VPort := Ntohs(LAddr.sin_port);
end;
function TIdStackLinux.WSGetSockOpt(ASocket: TIdStackSocketHandle; Alevel, AOptname: Integer; AOptval: PChar; var AOptlen: Integer): Integer;
begin
Result := libc.GetSockOpt(ASocket, ALevel, AOptname, AOptval, Cardinal(AOptlen));
end;
{ TIdSocketListLinux }
procedure TIdSocketListLinux.Add(AHandle: TIdStackSocketHandle);
Begin
FD_SET(AHandle, FFDSet);
FMaxHandle := Max(FMaxHandle, AHandle + 1);
End;//
function TIdSocketListLinux.Count: Integer;
var
I: Integer;
Begin
Result := 0;
for i:= 0 to __FD_SETSIZE - 1 do begin //? use FMaxHandle div x
if FD_ISSET(i, FFDSet) then begin
inc(Result);
end;
end;
End;//
function TIdSocketListLinux.GetItem(AIndex: Integer): TIdStackSocketHandle;
var
LIndex, i: Integer;
Begin
Result := 0;
LIndex := 0;
for i:= 0 to __FD_SETSIZE - 1 do begin //? use FMaxHandle div x
if FD_ISSET(i, FFDSet) then begin
if LIndex = AIndex then begin
Result := i;
Break;
end else begin
inc(LIndex);
end;
end;//if item
end;
End;//
procedure TIdSocketListLinux.Remove(AHandle: TIdStackSocketHandle);
var
i: Integer;
Begin
FD_CLR(AHandle, FFDSet);
if AHandle+1 >= FMaxHandle then begin
for i:=__FD_SETSIZE - 1 downto 0 do begin
if FD_ISSET(i, FFDSet) then begin
FMaxHandle := i + 1;
Break;
end;
end;
end;
End;//
function TIdStackLinux.WSTranslateSocketErrorMsg(
const AErr: integer): string;
//we override this function for the herr constants that
//are returned by the DNS functions
begin
case AErr of
libc.HOST_NOT_FOUND : Result := RSStackHOST_NOT_FOUND;
libc.TRY_AGAIN : Result := RSStackTRY_AGAIN;
libc.NO_RECOVERY : Result := RSStackNO_RECOVERY;
libc.NO_DATA : Result := RSStackNO_DATA;
else
Result := inherited WSTranslateSocketErrorMsg(AErr);
end;
end;
INITIALIZATION
GSocketListClass := TIdSocketListLinux;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -