On 12/18/2012 8:15 AM, Rudolf Thilo wrote:
[color=blue]
Hi Hamish,
I’m wondering, whether I should drop a feature request at the
developers forum of Autoit, to implement “non-blocking sockets” as
well. As I have no clue, how you did that trick: Would you mind to
share the source, so that I could point them to your code to see, how
it’s done / how much work this might be?[/color]
The code is quick and dirty, but you/they are welcome to it. It’s below,
in it’s entirety, at the end of this post.
[color=blue]
One feature that might be nice would be the option to specify the
protocol as well, e.g. UDP:69, or icmpv4:8 [1 → PING][/color]
UDP I could add fairly easily, icmp would require using raw sockets
(which I’ve no idea on and no references to look at, but will see what I
can find), or possibly do-able using the icmp.dll - I’ll look into it
when I have time.
[color=blue]
But this is just an idea, not something I currently need (and,
honestly, I have no clue at all, how much work these features might be)[/color]
H.
program chkPort;
// Input: chkport-ip [timeout]
// Output: Text message + Errorlevel
// 0 if we connect,
// 1 if we timeout,
// 2 if we get a socket failure,
// 3 for an invalid address.
uses sockets,inetaux,strutils,winsock2,sysutils;
var
ConSock : LongInt;
sAddr : TInetSockAddr;
timeout : dword;
result : boolean;
procedure setnonblockingsocket( s : integer );
var
nb : dword;
begin
nb := 1; // 1 = nonblocking, 0 = blocking
winsock2.ioctlsocket( s , FIONBIO , @nb );
end;
function is_writable_socket( sck : integer; timeout : dword ) : boolean;
var
fds : tfdset;
tv : timeval;
result : boolean;
begin
fd_zero( fds );
fd_set( sck , fds );
tv.tv_sec := timeout div 1000;
tv.tv_usec := timeout mod 1000;
// select (socket+1 , read , write , except , timeout) - wait
// “timeout” to see if data can be written to “socket” without
// blocking
result := select( sck + 1 , nil , @fds , nil , @tv ) > 0;
is_writable_socket := result;
end;
begin
// create a socket, die if we fail
ConSock := Socket(af_inet, sock_stream, 0);
if ConSock = -1 then begin
writeln('Could not open socket: ');
halt(2);
end
else begin
// make it non-blocking
SetNonBlockingSocket(ConSock);
// if timeout defined use it, otherwise default to 2 secs
If paramcount >= 3 then Timeout := numb2dec(paramstr(3),10)
else timeout := 2000;
// fill in the socket info - protocol, address, port
with sAddr do begin
Family := af_inet;
Port := htons(numb2dec(paramstr(2),10));
Addr := StrToAddr(paramstr(1));
end;
// die if we can’t turn the address into something useable
If saddr.Addr = 0 then begin
writeln('Could not resolve ',paramstr(1));
halt(3);
end;
// otherwise try to connect
Result := (fpConnect(ConSock, @sAddr, sizeof(sAddr)) = 0);
// and see if it become writeable in the time allowed
result := result or is_writable_socket(consock, timeout);
// close the socket
Shutdown(ConSock, 2);
// and report results
If result then writeln(‘Port listening’)
else begin
Writeln(‘Port not listening’);
halt(1);
end;
end;
end.