Extra Systems Database
unit inet;
interface
uses
winsock, windows;
type
TSocket = class(TObject)
private
FWaitRead : Integer;
FWaitWrite : Integer;
function ResolveHost(const HostName:PChar; var HostAddress:TInAddr):Boolean;
function IsIpDone(const Server:PChar):Boolean;
public
Handle : Integer;
ServerAddress : TSockAddrIn;
ClientAddress : TSockAddrIn;
constructor Create(const WaitRead,WaitWrite:Integer);
destructor Destroy; override;
function SendBuffer(const BufAddr:Pointer; const BufSize:Integer):Boolean;
function ReadToBuffer(const BufAddr:Pointer; const BufSize:Integer):Integer;
procedure Close;
function TestRead:Boolean;
function Connect(const Server:PChar; const Port:Integer):Boolean;
end;
{$EXTERNALSYM socket}
function socket(af, Struct, protocol: Integer): Integer; stdcall;
implementation
function socket; external 'wsock32.dll' name 'socket';
constructor TSocket.Create(const WaitRead,WaitWrite:Integer);
var
WSAData: TWSAData;
begin
inherited Create;
Handle:=0;
FWaitRead:=WaitRead;
FWaitWrite:=WaitWrite;
WinSock.WSAStartup($0101, WSAData);
end;
destructor TSocket.Destroy;
begin
if (Handle <> 0) then Close;
inherited Destroy;
WSACleanup;
end;
function TSocket.SendBuffer(const BufAddr:Pointer; const BufSize:Integer):Boolean;
var
i:Integer;
TimeVal:TTimeVal;
FDSet:TFDSet;
Done,ToSend,CurSend:Integer;
begin
Result:=False;
if ((Handle = 0) or (BufSize = 0)) then Exit;
Result:=True;
Done:=0;
ToSend:=BufSize;
while (Result and (ToSend > 0)) do begin
CurSend:=ToSend;
if (CurSend > 1024) then CurSend:=1024;
TimeVal.tv_sec := FWaitWrite;
TimeVal.tv_usec := 0;
FD_ZERO(FDSet);
FD_SET(Handle, FDSet);
i:=select(0, nil, @FDSet, nil, @TimeVal);
if (i > 0) then begin
Result:=(send(Handle, Pointer(Longint(BufAddr) + Done)^, CurSend, 0) = CurSend);
end else begin
Result:=False;
end;
if Result then begin
Done:=Done + CurSend;
ToSend:=ToSend - CurSend;
end;
end;
end;
procedure TSocket.Close;
begin
if (Handle = 0) then Exit;
shutdown(Handle, 2);
closesocket(Handle);
Handle:=0;
end;
function TSocket.TestRead:Boolean;
var
TimeVal : TTimeVal;
FDSet : TFDSet;
begin
Result:=(Handle <> 0);
if not Result then Exit;
TimeVal.tv_sec:=FWaitRead;
TimeVal.tv_usec:=0;
FD_ZERO(FDSet);
FD_SET(Handle, FDSet);
Result:=(select(0, @FDSet, nil, nil, @TimeVal) > 0);
end;
function TSocket.ReadToBuffer(const BufAddr:Pointer; const BufSize:Integer):Integer;
begin
Result:=0;
if TestRead then begin
Result:=recv(Handle, BufAddr^, BufSize, 0);
end;
end;
function TSocket.ResolveHost(const HostName:PChar; var HostAddress:TInAddr):Boolean;
var
HostEnt:PHostEnt;
begin
HostEnt:=WinSock.gethostbyname(HostName);
if (HostEnt = nil) then begin
Result:=False;
end else begin
HostAddress.S_un_b.s_b1:=HostEnt^.h_addr^[0];
HostAddress.S_un_b.s_b2:=HostEnt^.h_addr^[1];
HostAddress.S_un_b.s_b3:=HostEnt^.h_addr^[2];
HostAddress.S_un_b.s_b4:=HostEnt^.h_addr^[3];
Result:=True;
end;
end;
function TSocket.IsIpDone(const Server:PChar):Boolean;
var
i:Integer;
j:Pointer;
k:Char;
begin
Result:=True;
i:=0;
j:=Server;
while Result do begin
k:=PChar(Longint(j) + i)^;
if (k = #0) then Break;
Result:=((k = '.') or (k in ['0'..'9']));
i:=i + 1;
end;
end;
function TSocket.Connect(const Server:PChar; const Port:Integer):Boolean;
var
i,j:Integer;
begin
Result:=False;
Handle:=WinSock.socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if (Handle = -1) then begin
Handle:=0;
Exit;
end;
ServerAddress.sin_family:=PF_INET;
ServerAddress.sin_port:=htons(Port);
if IsIpDone(Server) then begin
ServerAddress.sin_addr.s_addr:=inet_addr(Server);
end else begin
if not ResolveHost(Server, ServerAddress.sin_addr) then begin
Close;
Exit;
end;
end;
if (WinSock.connect(Handle, ServerAddress, SizeOf(ServerAddress)) <> 0) then begin
Close;
end else begin
Result:=True;
i:=1;
j:=Sizeof(i);
setsockopt(Handle, IPPROTO_TCP, TCP_NODELAY, @i, j);
end;
end;
end.