LAN Web TCP Delphi

Title: Simple functions to get raw html page (with or without proxy)
Question: Here is some functions to retreive a web paget.
The code don't use any components or thread. Only pure windows api. It is usefull for console app that need to get a particular page from a server. It also works with Proxy.
Answer:
DESCRIPTION
-----------
This functions are not embeded in classes. It is good-old-dos-in-line programming, and it works fine for my console app (a Web server security checker).
There is 2 functions in U_HTTP.PAS :
function HttpGet(const site, path, port : string ; var res : string) : integer;
IN :
site is the web site to connect to (eg 'www.delphi3000.com')
path is the path of the web page (eg 'index.html')
port is a string for the TCP port to connect to (eg '80')
OUT :
res is the raw web page, with the HTTP header.
return an error code(
Function HttpGetEx(var Request : THttpRequest) : integer;
is an extension of the first function. It can use proxy to retreive data.
You have to fill the THttpRequest struct before calling the function. This
struct is use to pass in and out parameters to the function (I prefere this
compared to OOP class).
IN :
THttpRequest.Site is the web site to connect to
THttpRequest.Path is the web page to retreive
THttpRequest.Port is the port to connect to
THttpRequest.UseProxy set it to TRUE if you use a proxy
THttpRequest.ProxyAddress is eventually the proxy address (eg 'proxy.prout.com')
THttpRequest.ProxyPort is the proxy port (eg '8080' or '3128')
THttpRequest.TimeOut is the maximum time, in seconds, before returning a timeout error
IN / OUT
THttpRequest.HttpCode set it to 1 when calling and the function will parse the http header and returning (in HttpCode) the HTTP status code (eg 200 if ok, 404 if page not found...)
OUT :
THttpRequest.Result is the raw web page
THttpRequest.ResultLen is the number of bytes returned (the length of Result)
THttpRequest.ResultCode is 0 if ok, or an error code ( THttpRequest.ResultTime is the time spend to retreive the data
return 0 if ok or an error code
The Error Code returned in both functions is a negative integer from -1 to -7.
You should check WSAGetLastError to have a more precise error.
SAMPLE PROGRAM
--------------
Make a console app and copy and past this code :
program SimpleHttp;
uses
WinSock,
U_Http in 'U_Http.pas',
u_SockUtil in 'u_SockUtil.pas';
{$R *.RES}
var
res : string;
Req : THttpRequest;
iRes : integer;
begin
// Fill the Request structure
Req.Site := 'www.delphi3000.com';
Req.Path := '/';
Req.Port := '80';
Req.Timeout := 4;
Req.UseProxy := true; // !! CHANGE THIS IF YOU DONT USE PROXY !!
Req.ProxyAddress := '130.142.153.7';
Req.ProxyPort := '8080';
Req.HttpCode := 1; // 1 : Yes, i will check for http status code
Writeln('Getting Data');
iRes := HttpGetEx(req);
if (iRes 0) then
begin
// It works
Writeln(Req.Result);
Writeln('Http code : ',Req.HttpCode);
Writeln('Length of data : ', Req.ResultLen);
Writeln('Getting in : ', Req.ResultTime, ' ms');
end
else
begin
// It fails
Writeln('Error number :', Req.ResultCode);
Writeln(SocketErrorMsg(WSAGetLastError));
end;
ReadLn;
end.
THE UNITS
---------
unit U_Http;
{** U_Http.pas
** 05/02/2001 by Jerome Forestier
** Unit to get raw HTML result. Use low level winsock
** api (in U_SockUtil.pas), so it can be used in console app.
** Usefull for checking exploit.
**}
interface
Uses
Windows,
Winsock,
U_SockUtil;
const
RCV_BUFSIZE = 512; // Size of the incomming data buffer
CRLF = #$0D#$0A; //
DEFAULT_TIMEOUT_SECOND = 10; //
// Error Code
OK = 0;
ERR_BIND = -1;
ERR_CONNECT = -2;
ERR_SEND = -3;
ERR_TIMEOUT = -4;
ERR_SELECT = -5;
ERR_RECV = -6;
ERR_PROXY_CONNECT = -7;
type
THttpRequest = packed record
Site : string; // in : site address (www.yahoo.com)
Path : string; // in : site path (/index.html)
Port : string; // in : site port number (80)
UseProxy : boolean; // in : use proxy for getting data
ProxyAddress : String; // in : proxy address (proxy.toto.com)
ProxyPort : string; // in : proxy port (3128)
Timeout : word ; // in : tiemout for getting data in seconds
Result : string; // out : raw html result
ResultLen : integer; // out : number of bytes returned
ResultCode : integer; // out : error code (if any)
ResultTime : longint; // out : time, in ms, to get the data
HttpCode : word; // in / out if 1, the http header will be parsed and the error code (404) returned in
// if 0, no check for error code
end;
function HttpGet(const site, path, port : string ; var res : string) : integer;
// The simpliest function to retreive html source of a page.
// Raw html is in res variable.
// The function return 0 if ok or an error code (ERR_xxx)
Function HttpGetEx(var Request : THttpRequest) : integer;
// Extended function to retreive html source of a page
// Request parameters is in/out. Check out THttpRequest type
// The function return the number of bytes retreived ( 0) if ok
// or an error code (ERR_xxx)
implementation
uses
sysutils;
procedure InitSocket;
var
wsData : TWsAData;
begin
WSAStartup($0101, wsData);
end;
procedure DeInitSocket;
begin
WSACleanup;
end;
procedure CheckHttpHeader(buf :PCHAR ; len : integer ; var errorcode : word);
// This is experimental !
// We enter in this proc only for the first incomming buffer,
// it _should_ contain the http header with the error code
// eg : HHTP/1.0 404 Not Founf
var
i : integer;
code : integer;
scode : pchar;
begin
if (ErrorCode 1) then
exit;
i := 0;
// We search for the first space
while (buf[i] ' ') and (buf[i] #0) and (i begin
inc(i);
end;
if (buf[i] = ' ') then
begin
// char after the space are the error code
scode := @buf[i+1];
code := StrToIntDef(Copy(scode,1,3), 0);
errorcode := code;
end
else
ErrorCode := 0;
end;
Function HttpGetEx(var Request : THttpRequest) : integer;
label
EndOfProc;
var
Socket : TSocket;
iBindType : Integer;
err : integer;
ToSend : string;
SndBuf : PCHAR;
RcvBuf : array[0..RCV_BUFSIZE] of char;
FD : TFDSet;
TimeOut : TTimeVal;
len : integer;
Time : longint;
begin
Time := GetTickCount;
result := -1;
Request.Result := '';
Request.ResultCode := 0;
Request.ResultLen := 0;
TimeOut.tv_sec := Request.Timeout;
TimeOut.tv_usec := 0;
FD_ZERO(FD);
iBindType := GET_PORT_AND_REMOTE_ADDR;
socket := CreateSocket(iBindType, SOCK_STREAM);
err := BindSocketToAddr(iBindType,
socket,
request.Port,
'TCP',
true);
if (err = SOCKET_ERROR) then
begin
Request.ResultCode := ERR_BIND;
Goto EndOfProc;
end;
if (Request.UseProxy) then
begin
err := ConnectToServer(iBindType, Socket,
Request.ProxyAddress, Request.ProxyPort, 'TCP');
if (err = SOCKET_ERROR) then
Request.ResultCode := ERR_PROXY_CONNECT;
end
else
begin
err := ConnectToServer(iBindType, Socket,
Request.Site, Request.Port, 'TCP');
if (err = SOCKET_ERROR) then
Request.ResultCode := ERR_CONNECT;
end;
if (err = SOCKET_ERROR) then
Goto EndOfProc;
if (Request.UseProxy) then
begin
ToSend := Format('GET http://%s:%s%s HTTP/1.0'+CRLF, [Request.Site, Request.Port, Request.Path]);
end
else
begin
ToSend := Format('GET %s HTTP/1.0'+CRLF, [Request.Path]);
end;
ToSend := ToSend+'Accept: */*'+CRLF;
ToSend := ToSend+'Accept-Language: en'+CRLF;
ToSend := ToSend+'Accept-Encoding: gzip'+CRLF;
ToSend := ToSend+'User-Agent: JemoreWebClient(AmstradOS; I)'+CRLF;
ToSend := ToSend+'Host: '+Request.Site+':'+Request.port+CRLF;
if (Request.UseProxy) then
ToSend := ToSend + 'Proxy-Connection: Keep-Alive'+CRLF
else
ToSend := ToSend + 'Connection: Keep-Alive'+CRLF;
ToSend := ToSend + CRLF+CRLF;
len := Length(ToSend) - 1;
SndBuf := PCHAR(ToSend);
FD_SET(socket, FD);
err := send(Socket, SndBuf^, len, 0);
if (err = SOCKET_ERROR) then
begin
Request.ResultCode := ERR_SEND;
goto EndOfProc;
end;
repeat
err := Select(FD_SETSIZE, @FD, nil, nil, @TimeOut);
if (err = 0) then
begin
Request.ResultCode := ERR_TIMEOUT;
break;
end
else if (err = SOCKET_ERROR) then
begin
Request.ResultCode := ERR_SELECT;
break;
end;
if (FD_ISSET(socket, FD)) then
begin
err := recv(Socket, RcvBuf, RCV_BUFSIZE, 0);
if (err = SOCKET_ERROR) then
begin
Request.ResultCode := ERR_RECV;
break;
end
else if (err 0) then
begin
rcvBuf[err] := #0;
if (Request.HttpCode = 1) then
CheckHttpHeader(RcvBuf, RCV_BUFSIZE, Request.HttpCode);
Request.Result := Request.Result + rcvBuf;
Request.ResultLen := Request.ResultLen + err;
end;
end;
until (err = 0);
EndOfProc :
DestroySocket(socket);
Request.ResultTime := GetTickCount - Time;
result := Request.ResultLen;
end;
function HttpGet(const site, path, port : string ; var res : string) : integer;
var
socket : TSocket;
iBindType : integer;
err : integer;
p : PCHAR;
RcvBuf : array[0..RCV_BUFSIZE] of char;
FD : TFDSet;
TimeOut : TTimeVal;
len : integer;
begin
FillChar(rcvBuf, RCV_BUFSIZE, 0);
TimeOut.tv_sec := DEFAULT_TIMEOUT_SECOND;
TimeOut.tv_usec := 0;
res := '';
FD_ZERO(FD);
iBindType := GET_PORT_AND_REMOTE_ADDR;
socket := CreateSocket(iBindType, SOCK_STREAM);
err := BindSocketToAddr(iBindType,
socket,
port,
'TCP',
true);
if (err = SOCKET_ERROR) then
begin
result := ERR_BIND;
exit;
end;
err := ConnectToServer(iBindType, Socket,
site, port, 'TCP');
if (err = SOCKET_ERROR) then
begin
result := ERR_CONNECT;
exit;
end;
p := PCHAR(Format('GET %s HTTP/1.0'+CRLF+CRLF+CRLF, [path]));
len := length(p) - 1;
FD_SET(socket, FD);
err := send(Socket, p^, len, 0);
if (err = SOCKET_ERROR) then
begin
result := ERR_SEND;
exit;
end;
repeat
err := Select(FD_SETSIZE, @FD, nil, nil, @TimeOut);
if (err = 0) then
begin
result := ERR_TIMEOUT;
exit;
end
else if (err = SOCKET_ERROR) then
begin
result := ERR_SELECT;
exit;
end;
if (FD_ISSET(socket, FD)) then
begin
err := recv(Socket, rcvBuf, RCV_BUFSIZE, 0);
if (err = SOCKET_ERROR) then
begin
result := ERR_RECV;
break;
end
else if (err 0) then
begin
rcvBuf[err] := #0;
res := res + rcvBuf;
end;
end;
until (err = 0);
DestroySocket(socket);
result := Ok;
end;
initialization
initSocket;
finalization
DeInitSocket;
end.
--------------------------------------------------------------------------------
WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
WMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWMWM
--------------------------------------------------------------------------------
unit u_SockUtil;
{** Based on Sockutil.c in
** "Network Windows Programming" by Alok K. Sinha
**}
interface
uses
Windows,
Winsock;
function WinSockInitialize : integer;
function GetHostAddress(const hostname : string) : u_long;
function GetLocalHostAddress : u_long;
function GetPortForService(const serviceName, protocol : string) : u_short;
function BindSocketToAddr(iBindType : integer ;
soc : TSocket;
servicename : string;
const protocolname : string;
fClient : BOOL) : integer;
function CreateSocket(iBindType : integer; type_ : integer) : TSocket;
procedure DestroySocket(socket : TSocket);
function ConnectToServer(iBindType : integer; soc : TSocket ;
HostName : string ; ServiceName : string ; ProtocolName : string) : integer;
function GetHostAddressIPStr(const hostname : string) : string;
function SocketErrorMsg(Error: integer) : string;
const
NETBIOS_NAME_LENGTH = 16;
DEFAULT_PORT_ADDR = 1;
FIXED_PORT_LOCAL_ADDR = 2;
GET_PORT_AND_LOCAL_ADDR = 3;
BIND_NETBIOS = 4;
BIND_IPX = 5;
GET_PORT_AND_REMOTE_ADDR = 6;
FIXED_PORT = 80;
CLIENT_QUEUE_SIZE = 5;
READ_WRITE_LOOP = 1;
SHUTDOWN = 'ShutDown';
type
TSockAddr_nb = packed record
snb_family : short;
snb_type : u_short;
snb_name : array[0..NETBIOS_NAME_LENGTH-1] of char;
end;
PSockAddr_nb = ^TSockAddr_nb;
TSockAddr_ipx = packed record
sa_family : short;
sa_netnum : array[0..4-1] of char;
sa_nodenum : array[0..6-1] of char;
sa_socket : u_short;
end;
PSockAddr_ipx = ^TSockAddr_ipx;
implementation
uses
SysUtils;
const
NETBIOS_UNIQUE_NAME = 0;
NSPROTO_IPX = 0;
NSPROTO_SPX = 1256;
NSPROTO_SPXII = 1257;
defIPXAddress : TSockAddr_ipx = ( sa_family : AF_IPX ;
sa_netnum : (#0,#0,#0,#0) ;
sa_nodenum: (#0,#0,#0,#0,#0,#0) ;
sa_socket : $4040
);
procedure SET_NETBIOS_SOCKADDR(snb : PSockAddr_nb ; type_ : word ; name : PCHAR ; port : char);
var
i : integer;
begin
snb^.snb_family := AF_NETBIOS;
snb^.snb_type := type_;
for i := 0 to NETBIOS_NAME_LENGTH - 1 do
begin
snb^.snb_name := ' ';
end;
i := 0;
while (name[i] #0) and (i begin
snb^.snb_name[i] := name[i];
end;
snb^.snb_name[NETBIOS_NAME_LENGTH - 1] := port;
end;
function WinSockInitialize : integer;
var
wVersionRequired : WORD;
wsaData : TwsaData;
begin
wVersionRequired := MAKEWORD(1,1);
result := WSAStartup(wVersionRequired, wsaData);
end;
function GetHostAddress(const hostname : string) : u_long;
var
pHostAddr : PHostEnt;
type
T = ^u_long;
begin
pHostAddr := gethostbyname(PCHAR(hostname));
if (pHostAddr = nil) then
begin
result := 0;
end
else
begin
result := T(pHostAddr^.h_addr^)^;
end;
end;
function GetLocalHostAddress : u_long;
var
szHostName : array[0..MAX_PATH] of char;
begin
if (gethostname(szHostName, SizeOf(szHostName)) SOCKET_ERROR) then
result := GetHostAddress(szHostName)
else
result := 0;
end;
function GetPortForService(const serviceName, protocol : string) : u_short;
var
pServAddr : PServent;
begin
pServAddr := getservbyname(PCHAR(servicename), PCHAR(protocol));
if (pServAddr nil) then
result := pServAddr^.s_port
else
result := u_short(-1);
end;
function BindSocketToAddr(iBindType : integer ;
soc : TSocket;
servicename : string;
const protocolname : string;
fClient : BOOL) : integer;
var
LocalAddr : TSockAddrIn;
NetBiosAddr : TSockAddr_nb;
IpxAddr : TSockAddr_ipx;
err : integer;
ulHostAddress : u_long;
usPortNo : u_short;
bReuse : BOOL;
szNbName : array[0..NETBIOS_NAME_LENGTH - 1] of char;
tmp : pchar;
begin
bReuse := true;
if (fClient) then
begin
if ((iBindType BIND_IPX) and (iBindType BIND_NETBIOS)) then
iBindType := DEFAULT_PORT_ADDR;
end;
FillChar(LocalAddr, SizeOf(LocalAddr), 00);
// err := SOCKET_ERROR;
case (iBindType) of
DEFAULT_PORT_ADDR :
begin
LocalAddr.sin_family := AF_INET;
LocalAddr.sin_addr.S_addr := htonl(INADDR_ANY);
LocalAddr.sin_port := 0;
end;
FIXED_PORT_LOCAL_ADDR :
begin
ulHostAddress := GetLocalHostAddress;
if (ulHostAddress = 0) then
begin
result := -1;
exit;
end;
LocalAddr.sin_family := AF_INET;
LocalAddr.sin_addr.s_addr := ulHostAddress;
LocalAddr.sin_port := htons(FIXED_PORT);
end;
GET_PORT_AND_LOCAL_ADDR :
begin
ulHostAddress := GetLocalHostAddress;
if (ulHostAddress = 0) then
begin
result := -1;
exit;
end
else
usPortNo := GetPortForService(ServiceName, ProtocolName);
if (usPortNo = 65535) then
usPortNo := htons(StrToIntDef(ServiceName, -1));
LocalAddr.sin_family := AF_INET;
LocalAddr.sin_addr.s_addr := ulHostAddress;
LocalAddr.sin_port := usPortNo;
end;
BIND_NETBIOS :
begin
usPortNo := GetPortForService(serviceName, ProtocolName);
if (usPortNo = 65535) then
usPortNo := htons(StrToIntDef(ServiceName, -1));
if (fClient) then
begin
serviceName := 'WSockClient';
end;
FillChar(szNbName, SizeOf(szNbName), 0);
Move(serviceName, szNbName, Length(ServiceName));
SET_NETBIOS_SOCKADDR(@NetBiosAddr, NETBIOS_UNIQUE_NAME, szNbName, CHAR(usPortNo));
end;
BIND_IPX:
begin
move(defIPXAddress, IpxAddr, SizeOf(TSOCKADDR_IPX));
tmp := PCHAR(ServiceName);
move(tmp, ipxAddr.sa_nodenum, 6);
tmp := PCHAR(ProtocolName);
move(tmp, ipxAddr.sa_netnum, 4);
if (fClient) then
ipxAddr.sa_socket := 0;
setsockopt(soc, SOL_SOCKET, SO_REUSEADDR, PCHAR(bReuse), 4);
end;
end;
if (iBindType = BIND_NETBIOS) then
err := bind(soc, TSockAddrIn(pSockAddrIn(@NetBiosAddr)^), SizeOf(NetBiosAddr))
else if (iBindType = BIND_IPX) then
err := bind(soc, TSockAddrIn(pSockAddrIn(@IpxAddr)^), SizeOf(IpxAddr))
else
err := bind(soc, TSockAddrIn(pSockAddrIn(@LocalAddr)^), SizeOf(LocalAddr));
result := err;
end;
function CreateSocket(iBindType : integer; type_ : integer) : TSocket;
var
soc : TSocket;
begin
case (iBindType) of
BIND_IPX :
begin
if (type_ = SOCK_STREAM) then
soc := Socket(AF_IPX, type_, NSPROTO_SPX)
else
soc := Socket(AF_IPX, type_, NSPROTO_IPX);
end;
BIND_NETBIOS :
begin
if (type_ = SOCK_STREAM) then
soc := Socket(AF_IPX, type_, SOCK_SEQPACKET)
else
soc := Socket(AF_IPX, type_, SOCK_DGRAM);
end;
else
begin
soc := Socket(AF_INET, type_, 0);
end;
end;
result := soc;
end;
function ConnectToServer(iBindType : integer; soc : TSocket ;
HostName : string ; ServiceName : string ; ProtocolName : string) : integer;
var
RemAddr : TSockAddrIn;
NetBiosAddr : TSockAddr_NB;
IpxAddr : TSockAddr_ipx;
err : integer;
ulHostAddress : u_long;
usPortNo : u_short;
begin
FillChar(RemAddr, 0, SizeOf(TSockAddrIn));
case (iBindType) of
DEFAULT_PORT_ADDR :
begin
result := SOCKET_ERROR;
exit;
end;
FIXED_PORT_LOCAL_ADDR :
begin
ulHostAddress := GetLocalHostAddress;
if (ulHostAddress = 0) then
begin
result := SOCKET_ERROR;
exit;
end;
RemAddr.sin_family := AF_INET;
RemAddr.sin_addr.S_addr := UlHostAddress;
RemAddr.sin_port := htons(FIXED_PORT);
end;
GET_PORT_AND_LOCAL_ADDR :
begin
ulHostAddress := GetLocalHostAddress;
if (ulHostAddress = 0) then
begin
result := SOCKET_ERROR;
exit;
end;
usPortNo := (GetPortForService(ServiceName, ProtocolName));
if (usPortNo = 65535) then
usPortNo := htons(StrToIntDef(ServiceName, -1));
RemAddr.sin_family := AF_INET;
RemAddr.sin_addr.s_addr := ulHostAddress;
RemAddr.sin_port := usPortNo;
end;
GET_PORT_AND_REMOTE_ADDR :
begin
ulHostAddress := GetHostAddress(HostName);
if (ulHostAddress = 0) then
begin
result := SOCKET_ERROR;
exit;
end;
usPortNo := (GetPortForService(ServiceName, ProtocolName));
if (usPortNo = 65535) then
usPortNo := htons(StrToIntDef(ServiceName, -1));
RemAddr.sin_family := AF_INET;
RemAddr.sin_addr.s_addr := ulHostAddress;
RemAddr.sin_port := usPortNo;
end;
BIND_IPX :
begin
Move(defIPXaddress, IpxAddr, SizeOf(TSockAddr_IPX));
end;
end;
if (iBindType = BIND_NETBIOS) then
err := connect(soc, TSockAddrIn(pSockAddrIn(@NetBiosAddr)^), SizeOf(NetBiosAddr))
else if (iBindType = BIND_IPX) then
err := connect(soc, TSockAddrIn(pSockAddrIn(@IpxAddr)^), SizeOf(IpxAddr))
else
err := Connect(soc, RemAddr, SizeOf(RemAddr));
result := Err;
end;
function GetHostAddressIPStr(const hostname : string) : string;
var
adr : u_long;
in_ : TInAddr;
begin
adr := GetHostAddress(hostname);
in_.S_addr := adr;
result := inet_ntoa(in_);
end;
function SocketErrorMsg(Error: integer) : string;
begin
case Error of
WSAEINTR:
SocketErrorMsg := 'Interrupted system call';
WSAEBADF:
SocketErrorMsg := 'Bad file number';
WSAEACCES:
SocketErrorMsg := 'Permission denied';
WSAEFAULT:
SocketErrorMsg := 'Bad address';
WSAEINVAL:
SocketErrorMsg := 'Invalid argument';
WSAEMFILE:
SocketErrorMsg := 'Too many open files';
WSAEWOULDBLOCK:
SocketErrorMsg := 'Operation would block';
WSAEINPROGRESS:
SocketErrorMsg := 'Operation now in progress';
WSAEALREADY:
SocketErrorMsg := 'Operation already in progress';
WSAENOTSOCK:
SocketErrorMsg := 'Socket operation on non-socket';
WSAEDESTADDRREQ:
SocketErrorMsg := 'Destination address required';
WSAEMSGSIZE:
SocketErrorMsg := 'Message too long';
WSAEPROTOTYPE:
SocketErrorMsg := 'Protocol wrong type for socket';
WSAENOPROTOOPT:
SocketErrorMsg := 'Protocol not available';
WSAEPROTONOSUPPORT:
SocketErrorMsg := 'Protocol not supported';
WSAESOCKTNOSUPPORT:
SocketErrorMsg := 'Socket type not supported';
WSAEOPNOTSUPP:
SocketErrorMsg := 'Operation not supported on socket';
WSAEPFNOSUPPORT:
SocketErrorMsg := 'Protocol family not supported';
WSAEAFNOSUPPORT:
SocketErrorMsg := 'Address family not supported by protocol family';
WSAEADDRINUSE:
SocketErrorMsg := 'Address already in use';
WSAEADDRNOTAVAIL:
SocketErrorMsg := 'Can''t assign requested address';
WSAENETDOWN:
SocketErrorMsg := 'Network is down';
WSAENETUNREACH:
SocketErrorMsg := 'Network is unreachable';
WSAENETRESET:
SocketErrorMsg := 'Network dropped connection on reset';
WSAECONNABORTED:
SocketErrorMsg := 'Software caused connection abort';
WSAECONNRESET:
SocketErrorMsg := 'Connection reset by peer';
WSAENOBUFS:
SocketErrorMsg := 'No buffer space available';
WSAEISCONN:
SocketErrorMsg := 'Socket is already connected';
WSAENOTCONN:
SocketErrorMsg := 'Socket is not connected';
WSAESHUTDOWN:
SocketErrorMsg := 'Can''t send after socket shutdown';
WSAETOOMANYREFS:
SocketErrorMsg := 'Too many references: can''t splice';
WSAETIMEDOUT:
SocketErrorMsg := 'Connection timed out';
WSAECONNREFUSED:
SocketErrorMsg := 'Connection refused';
WSAELOOP:
SocketErrorMsg := 'Too many levels of symbolic links';
WSAENAMETOOLONG:
SocketErrorMsg := 'File name too long';
WSAEHOSTDOWN:
SocketErrorMsg := 'Host is down';
WSAEHOSTUNREACH:
SocketErrorMsg := 'No route to host';
WSAENOTEMPTY:
SocketErrorMsg := 'Directory not empty';
WSAEPROCLIM:
SocketErrorMsg := 'Too many processes';
WSAEUSERS:
SocketErrorMsg := 'Too many users';
WSAEDQUOT:
SocketErrorMsg := 'Disc quota exceeded';
WSAESTALE:
SocketErrorMsg := 'Stale NFS file handle';
WSAEREMOTE:
SocketErrorMsg := 'Too many levels of remote in path';
WSASYSNOTREADY:
SocketErrorMsg := 'Network sub-system is unusable';
WSAVERNOTSUPPORTED:
SocketErrorMsg := 'WinSock DLL cannot support this application';
WSANOTINITIALISED:
SocketErrorMsg := 'WinSock not initialized';
WSAHOST_NOT_FOUND:
SocketErrorMsg := 'Host not found';
WSATRY_AGAIN:
SocketErrorMsg := 'Non-authoritative host not found';
WSANO_RECOVERY:
SocketErrorMsg := 'Non-recoverable error';
WSANO_DATA:
SocketErrorMsg := 'No Data';
else
SocketErrorMsg := 'Unknown WinSock error';
end;
end;
procedure DestroySocket(socket : TSocket);
begin
Winsock.Shutdown(socket,1);
CloseSocket(Socket);
end;
end.
// Tested with D3 and NT4