{ Declaration of global variables }
var
WaitTimeMs: WORD;
InitialTick, DifTick: DWORD;
procedure TForm.FormCreate(Sender: TObject);
begin
Randomize; // Generates a new random randomizing seed
end;
{ Auxiliary Winsock blocking hook function (can't be an object method).
Consult Winsock API WSASetBlockingHook function for details }
function BlockingHookProc: Boolean; stdcall;
begin
{ Returns False to end Winsock internal testing loop }
Result := False;
{ Verify time expiration, taking into account rare but possible counter recycling (49.7 days) }
if GetTickCount < InitialTick then DifTick := $FFFFFFFF - InitialTick + GetTickCount
else
DifTick := GetTickCount - InitialTick;
{ Limit time expired, then cancel Winsock operation }
if (DifTick > WaitTimeMs) and WSAIsBlocking then WSACancelBlockingCall;
end;
function IsConnectedToNet(HostIP: string; HostPort, CancelTimeMs: Word;
FirstOctet: Byte; PError: PChar): Boolean;
var
GInitData: TWSADATA;
SockDescript: TSocket;
SockAddr: TSockAddr;
NameLen: Integer;
{ Auxiliary procedure just to format error string }
procedure SaveError(Proc: string; const LastError: Integer);
begin
StrLCopy(PError, PChar(Proc + ' - Error no.' + IntToStr(LastError)), 255);
end;
{ Auxiliary function to return a random IP address, but keeping some desired octets fixed.
FirstOctet gives the order of the octet (1 to 4, left to right) from which to randomize }
function GetRandomSimilarIP(InitIP: string): string;
var
Index: Integer;
P1, P2: PChar;
begin
Result := '';
InitIP := InitIP + '.'; // Final dot added to simplify algorithm
P1 := @InitIP[1];
for Index := 1 to 4 do
begin // Extracts octets from initial IP address
P2 := StrPos(P1, '.');
if Index < FirstOctet then Result := Result + Copy(P1, 0, P2 - P1)
else
Result := Result + IntToStr(1 + Random(254));
if Index < 4 then Result := Result + '.'
else
Break;
P1 := P2 + 1;
end;
end;
begin
{ Inicializes as not connected }
Result := False;
WaitTimeMs := CancelTimeMs;
{ Inicializes error string }
if PError <> nil then PError[0] := #0;
{ Inicializes Winsock }
if WSAStartup($101, GInitData) <> 0 then
begin
if PError <> nil then SaveError('WSAStartup', WSAGetLastError);
Exit;
end;
try
{ Establishes Winsock blocking hook routine }
if WSASetBlockingHook(@BlockingHookProc) = nil then
begin
if PError <> nil then SaveError('WSASetBlockingHook', WSAGetLastError);
Exit;
end;
try
{ Creates a new socket }
SockDescript := Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if SockDescript = INVALID_SOCKET then
begin
if PError <> nil then SaveError('Socket', WSAGetLastError);
Exit;
end;
try
{ Initializes local socket data }
SockAddr.sin_family := AF_INET;
SockAddr.sin_port := 0; // System will choose local port from 1024 to 5000
SockAddr.sin_addr.S_addr := 0;
// System will choose local IP address, if multi-homed
{ Associates local IP and port with local socket }
if Bind(SockDescript, SockAddr, SizeOf(SockAddr)) <> 0 then
begin
if PError <> nil then SaveError('Bind', WSAGetLastError);
Exit;
end;
{ Initializes remote socket data }
SockAddr.sin_family := AF_INET;
SockAddr.sin_port := htons(HostPort); // Any port number different from 0
if FirstOctet in [1, 4] then // Any valid IP address on desired subnet
SockAddr.sin_addr := in_addr(inet_addr(PChar(GetRandomSimilarIP(HostIP))))
else
SockAddr.sin_addr := in_addr(inet_addr(PChar(HostIP)));
{ Inicializes time counter }
InitialTick := GetTickCount;
{ Tries to connect }
if Connect(SockDescript, SockAddr, SizeOf(SockAddr)) <> 0 then
begin
{ Tests if it is connected }
Result := (WSAGetLastError = WSAECONNREFUSED) or // Connection refused (10061)
(WSAGetLastError = WSAEINTR) or
// Interrupted system call (10004)
(WSAGetLastError = WSAETIMEDOUT);
// Connection timed out (10060)
{ It may have occurred an error but testing indicated being connected }
if PError <> nil then SaveError('Connect', WSAGetLastError);
end
{ No error }
else
begin
NameLen := SizeOf(SockAddr);
{ Tries to get remote IP address and port }
Result := (GetPeerName(SockDescript, SockAddr, NameLen) = 0);
if not Result and (PError <> nil) then
SaveError('GetPeerName', WSAGetLastError);
end;
finally
CloseSocket(SockDescript); // Frees the socket
end;
finally
WSAUnhookBlockingHook; // Deactivates the blocking hook
end;
finally
WSACleanup; // Frees Winsock
end;
end;
你可以用以下方法, 判斷一個程序是不是死掉了, 但象你這種情況, 也可以你一段時間沒有流量, 電信局自動中止! 這種, 你只能用檢查網絡聯接的方法
function AppIsResponding(ClassName: string): Boolean;
const
{ Specifies the duration, in milliseconds, of the time-out period }
TIMEOUT = 50;
var
Res: DWORD;
h: HWND;
begin
h := FindWindow(PChar(ClassName), nil);
if h <> 0 then
Result := SendMessageTimeOut(H,
WM_NULL,
0,
0,
SMTO_NORMAL or SMTO_ABORTIFHUNG,
TIMEOUT,
Res) <> 0
else
ShowMessage(Format('%s not found!', [ClassName]));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if AppIsResponding('OpusApp') then
{ OpusApp is the Class Name of WINWORD }
ShowMessage('App. responding');
end;