首页  编辑  

检测计算机的 Internet 连接状态

Tags: /超级猛料/Network.网络通讯/其它/   Date Created:

if GetSystemMetrics(SM_NETWORK) AND $01 = $01 then

ShowMessage('Machine is attached to network') else

ShowMessage('Machine is not attached to network');

---------------------------------------

DWORD dwConnectState;

CString strConnectState;

BOOL bOK = InternetGetConnectedState( &dwConnectState, 0);

if ( bOK )

{

 if ( dwConnectState & INTERNET_CONNECTION_LAN )

   strConnectState = "Local system uses a local area network to connect to the Internet. ";

 if ( dwConnectState & INTERNET_CONNECTION_MODEM )

   strConnectState = "Local system uses a modem to connect to the Internet. ";

 if ( dwConnectState & INTERNET_CONNECTION_MODEM_BUSY )

   strConnectState = "No longer used. ";

 if ( dwConnectState = INTERNET_CONNECTION_PROXY )

   strConnectState = "Local system uses a proxy server to connect to the Internet. ";

}

测试连接是否有效,可以用:InternetCheckConnection

检测计算机是否联网比较简单的做法可以通过一个 Win32 Internet(WinInet) 函数 InternetCheckConnection来实现;

这个函数的功能是检查是否能够建立 Internet 连接。

它的实现是在 %SystemRoot%\System32\wininet.dll 中,Delphi 调用声明在 WinInet.pas 中,

其 API 声明如下:

BOOL InternetCheckConnection(

   IN LPCSTR lpszUrl,

   IN DWORD dwFlags,

   IN DWORD dwReserved

);

参数的意义是:

lpszUrl: 需要测试能否建立连接的 URL 地址,可以为空;

dwFlags: 目前只能是 FLAG_ICC_FORCE_CONNECTION(这个常量 Delphi 中没有声明,其值为 $00000001);

dwReserved: 目前只能为 0。

调用的说明:

如果 lpszUrl 是非空的,Windows 从中解析出 Host 名然后 Ping 这个指定的 Host。

如果 lpszUrl 是空的,并且 WinInet 内部服务器的 database 中有一个关于最近的 Server 的纪录,Windows 就从这条纪录中解析出 Host 名然后 Ping 它。

如果能够成功的连接返回 True,否则返回 False;

以下是一个判断当前计算机是否联网的例子:

procedure TForm1.Button1Click(Sender: TObject);

begin

   if InternetCheckConnection('http://www.yahoo.com/', 1, 0) then

       edit1.text:= 'Connected'

   else

       edit1.text:= 'Disconnected';

end;

通过上述的方法只能检测出当前计算机是否物理联网,即网线是否接好,网卡是否能顺利工作,不能确定是否能够实现获得 Internet 服务,即是否能和 ISP 进行 Internet 连接。

这时可以通过另一个 Win32 Internet(WinInet) 函数 InternetQueryOption 来检测;

这个函数的功能是查询指定 Internet 句柄的状态、选项。

其 API 声明如下:

BOOL InternetQueryOption(

   IN HINTERNET hInternet,

   IN DWORD dwOption,

   OUT LPVOID lpBuffer,

   IN OUT LPDWORD lpdwBufferLength

);

参数的意义是:

hInternet:查询对象的 Internet 句柄(全局查询时为 nil),

dwOption:查询的项目;

lpBuffer:返回的查询结果;

lpdwBufferLength:查询结果的字节长度(包括 IN 和 OUT);

查询成功返回 True,否则返回 False;

我们要查询当前计算机的 Internet 连接状态时可以使用查询项目 INTERNET_OPTION_CONNECTED_STATE,

得到的 ConnectState 返回值可能是以下值的一个或几个值之和:

INTERNET_STATE_CONNECTED               :$00000001 连接状态;

INTERNET_STATE_DISCONNECTED            :$00000002 非连接状态(和 INTERNET_STATE_CONNECTED 对应);

INTERNET_STATE_DISCONNECTED_BY_USER    :$00000010 用户请求的非连接状态

INTERNET_STATE_IDLE                    :$00000100 连接状态,并且空闲

INTERNET_STATE_BUSY                    :$00000200 连接状态,正在响应连接请求

以下是一个判断当前计算机是否可以获得 Internet 服务的例子:

function TForm1.CheckOffline: boolean;

var

   ConnectState: DWORD;

   StateSize: DWORD;

begin

   ConnectState:= 0;

   StateSize:= SizeOf(ConnectState);

   result:= false;

   if InternetQueryOption(nil, INTERNET_OPTION_CONNECTED_STATE, @ConnectState, StateSize) then

       if (ConnectState and INTERNET_STATE_DISCONNECTED) <> 2 then result:= true;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

   if CheckOffline then

       edit1.text:= 'Connect To ISP'

   else

       edit1.text:= 'Disconnect To ISP';

end;

需要说明的是 InternetQueryOption 函数的检测结果只能表明当前的 Internet 设置是可用的,

并不能表示计算机一定能访问 Internet,例如网线掉了,网卡突然坏了之类的错误就没法检测出来,

要想检测当前计算机是否能够获得 Internet 服务了必须两个函数结合起来使用。

以上程序在 Win2000, Delphi5.0 下调试通过。

最后要提醒大家注意的是在 uses 中要加上 WinInet。

*********************************************************

check if I am connected to the internet?

interface

uses

 Windows, SysUtils, Registry, WinSock, WinInet;

type

 TConnectionType = (ctNone, ctProxy, ctDialup);

function ConnectedToInternet: TConnectionType;

function RasConnectionCount: Integer;

implementation

//For RasConnectionCount =======================

const

 cERROR_BUFFER_TOO_SMALL = 603;

 cRAS_MaxEntryName       = 256;

 cRAS_MaxDeviceName      = 128;

 cRAS_MaxDeviceType      = 16;

type

 ERasError = class(Exception);

 HRASConn = DWORD;

 PRASConn = ^TRASConn;

 TRASConn = record

   dwSize: DWORD;

   rasConn: HRASConn;

   szEntryName: array[0..cRAS_MaxEntryName] of Char;

   szDeviceType: array[0..cRAS_MaxDeviceType] of Char;

   szDeviceName: array [0..cRAS_MaxDeviceName] of Char;

 end;

 TRasEnumConnections =

   function(RASConn: PrasConn; { buffer to receive Connections data }

   var BufSize: DWORD;    { size in bytes of buffer }

   var Connections: DWORD { number of Connections written to buffer }

   ): Longint;  

 stdcall;

 //End RasConnectionCount =======================

function ConnectedToInternet: TConnectionType;

var

 Reg:       TRegistry;

 bUseProxy: Boolean;

 UseProxy:  LongWord;

begin

 Result := ctNone;

 Reg    := TRegistry.Create;

 with REG do

   try

     try

       RootKey := HKEY_CURRENT_USER;

       if OpenKey('\Software\Microsoft\Windows\CurrentVersion\Internet settings', False) then  

       begin

         //I just try to read it, and trap an exception

         if GetDataType('ProxyEnable') = rdBinary then

           ReadBinaryData('ProxyEnable', UseProxy, SizeOf(Longword))

         else  

         begin

           bUseProxy := ReadBool('ProxyEnable');

           if bUseProxy then

             UseProxy := 1

           else

             UseProxy := 0;

         end;

         if (UseProxy <> 0) and (ReadString('ProxyServer') <> '') then

           Result := ctProxy;

       end;

     except

       //Obviously not connected through a proxy

     end;

   finally

     Free;

   end;

 //We can check RasConnectionCount even if dialup networking is not installed

 //simply because it will return 0 if the DLL is not found.

 if Result = ctNone then  

 begin

   if RasConnectionCount > 0 then Result := ctDialup;

 end;

end;

function RasConnectionCount: Integer;

var

 RasDLL:    HInst;

 Conns:     array[1..4] of TRasConn;

 RasEnums:  TRasEnumConnections;

 BufSize:   DWORD;

 NumConns:  DWORD;

 RasResult: Longint;

begin

 Result := 0;

 //Load the RAS DLL

 RasDLL := LoadLibrary('rasapi32.dll');

 if RasDLL = 0 then Exit;

 try

   RasEnums := GetProcAddress(RasDLL, 'RasEnumConnectionsA');

   if @RasEnums = nil then

     raise ERasError.Create('RasEnumConnectionsA not found in rasapi32.dll');

   Conns[1].dwSize := SizeOf(Conns[1]);

   BufSize         := SizeOf(Conns);

   RasResult := RasEnums(@Conns, BufSize, NumConns);

   if (RasResult = 0) or (Result = cERROR_BUFFER_TOO_SMALL) then Result := NumConns;

 finally

   FreeLibrary(RasDLL);

 end;

end;