我们的应用程序的某些功能,可能需要一个互联网连接的运行时间测试。 一旦检测到互联网连接,可能会暂时被禁用的功能需要访问Internet和/或用户可以通过警报消息通知。 否则,应用程序可能会导致在操作过程中的错误,否则可能会导致恼人的问题.
引用这里: http://www.codeproject.com/Tips/147662/Testing-Internet-Connectivity
Method 1: WebRequest
We may send a web request to a website which assumed to be online always, for example google.com. If we can get a response, then obviously the device that runs our application is connected to the internet.
public static bool WebRequestTest()
{
string url = "http://www.google.com";
try
{
System.Net.WebRequest myRequest = System.Net.WebRequest.Create(url);
System.Net.WebResponse myResponse = myRequest.GetResponse();
}
catch (System.Net.WebException)
{
return false;
}
return true;
}
Method 2: TCP Socket
There can be some delay in response of web request therefore this method may not be fast enough for some applications. A better way is to check whether port 80, default port for http traffic, of an always online website.
public static bool TcpSocketTest()
{
try
{
System.Net.Sockets.TcpClient client =
new System.Net.Sockets.TcpClient("www.google.com", 80);
client.Close();
return true;
}
catch (System.Exception ex)
{
return false;
}
}
Method 3: Ping
There can be some delay in response of web request, therefore this method may not be fast enough for some applications. A better way is to check whether port 80, default port for http traffic, of an always online website.
public bool PingTest()
{
System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply pingStatus =
ping.Send(IPAddress.Parse("208.69.34.231"),1000);
if (pingStatus.Status == System.Net.NetworkInformation.IPStatus.Success)
{
return true;
}
else
{
return false;
}
}
You cannot use this method in .NET Compact Framework because there is no NetworkInformation
namespace that comes with Compact Framework. However, you can use Smart Device Framework (http://www.opennetcf.com[^], Community Edition is free for download) provided by OpenNETCF. This framework comes with many other useful tools that .NET Compact Framework does not contain.
Notice that I used Google’s IP address 208.69.34.231
. We could use Google’s web address www.google.com
:
System.Net.NetworkInformation.PingReply pingStatus = ping.Send("www.google.com",1000);
However, that will require DNS lookup which causes extra delay.
Method 4: DNS Lookup
Alternatively you can use DNS lookup to check internet connectivity. This method is faster than Ping method.
public static bool DnsTest()
{
try
{
System.Net.IPHostEntry ipHe =
System.Net.Dns.GetHostByName("www.google.com");
return true;
}
catch
{
return false;
}
}
Method 5: Windows Internet API (WinINet)
WinINet
API provides functions to test internet connectivity, such as InternetCheckConnection
andInternetGetConnectedState
. I do not have any idea about what these fucntions do exactly to test internet connectivity. You may refer to http://msdn.microsoft.com/en-us/library/aa384346(v=VS.85).aspx andhttp://msdn.microsoft.com/en-us/library/aa384702(v=VS.85).aspx for details.
An example usage can be:
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int connDescription, int ReservedValue);
//check if a connection to the Internet can be established
public static bool IsConnectionAvailable()
{
int Desc;
return InternetGetConnectedState(out connDesc, 0);
}
更多示例:收集网络
0 Detect Internet Network Availability
这个示例很好,自带监听网络状态:http://www.codeproject.com/Articles/64975/Detect-Internet-Network-Availability
1. win32 API函数的做法:
要用的函数:InternetGetConnectedState
函数原形:BOOL InternetGetConnectedState(LPDWORD lpdwFlags,DWORD dwReserved);
参数lpdwFlags返回当前网络状态,,参数dwReserved依然是保留参数,设置为0即可。
INTERNET_CONNECTION_MODEM 通过调治解调器连接网络
INTERNET_CONNECTION_LAN 通过局域网连接网络
这个函数的功能是很强的。它可以:
1. 判断网络连接是通过网卡还是通过调治解调器
2. 是否通过代理上网
3. 判断连接是On Line还是Off Line
4. 判断是否安装“拨号网络服务”
5. 判断调治解调器是否正在使用
这个win32 API在系统system32文件夹中wininet.dll中
使用这个判断的话,需要在类中这样写:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace API
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private const int INTERNET_CONNECTION_MODEM = 1;
private const int INTERNET_CONNECTION_LAN = 2;
[DllImport("wininet.dll")]
private static extern bool InternetGetConnectedState(ref int dwFlag, int dwReserved);
private void button1_Click(object sender, EventArgs e)
{
System.Int32 dwFlag = new int();
if (!InternetGetConnectedState(ref dwFlag, 0))
{
MessageBox.Show("未连网!");
}
else if ((dwFlag & INTERNET_CONNECTION_MODEM) != 0)
{
MessageBox.Show("采用调治解调器上网!");
}
else if((dwFlag & INTERNET_CONNECTION_LAN)!=0)
{
MessageBox.Show("采用网卡上网!");
}
}
}
}
2. 采用PING的方法 ping一个常见域名,如果ping通则网络正常
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.NetworkInformation;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Ping p = new Ping();//创建Ping对象p
PingReply pr = p.Send("10.13.88.111");//向指定IP或者主机名的计算机发送ICMP协议的ping数据包
if (pr.Status == IPStatus.Success)//如果ping成功
{
Console.WriteLine("网络连接成功, 执行下面任务...");
}
else
{
int times = 0;//重新连接次数;
do
{
if (times >= 12)
{
Console.WriteLine("重新尝试连接超过12次,连接失败程序结束");
return;
}
Thread.Sleep(1000);//等待
pr = p.Send("10.13.88.111");
Console.WriteLine(pr.Status);
times++;
}
while (pr.Status != IPStatus.Success);
Console.WriteLine("连接成功");
times = 0;//连接成功,重新连接次数清为0;
}
}
}
}
一个完整的示例
ASP.net网站程序运行的时候,某些情况下需要判断网络的连通状态,包括局域网、互联网、aol等,甚至某个具体网站的连通情况。以下类库可以实现联网状态检测:
using System;
using System.Web;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
namespace VvxT.Web
{
public class Internet
{
#region 利用API方式获取网络链接状态
private static int NETWORK_ALIVE_LAN = 0x00000001;
private static int NETWORK_ALIVE_WAN = 0x00000002;
private static int NETWORK_ALIVE_AOL = 0x00000004;
[DllImport("sensapi.dll")]
private extern static bool IsNetworkAlive(ref int flags);
[DllImport("sensapi.dll")]
private extern static bool IsDestinationReachable(string dest, IntPtr ptr);
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(out int connectionDescription, int reservedValue);
public Internet() { }
public static bool IsConnected()
{
int desc = 0;
bool state = InternetGetConnectedState(out desc, 0);
return state;
}
public static bool IsLanAlive()
{
return IsNetworkAlive(ref NETWORK_ALIVE_LAN);
}
public static bool IsWanAlive()
{
return IsNetworkAlive(ref NETWORK_ALIVE_WAN);
}
public static bool IsAOLAlive()
{
return IsNetworkAlive(ref NETWORK_ALIVE_AOL);
}
public static bool IsDestinationAlive(string Destination)
{
return (IsDestinationReachable(Destination, IntPtr.Zero));
}
#endregion
/// <summary>
/// 在指定时间内尝试连接指定主机上的指定端口。 (默认端口:80,默认链接超时:5000毫秒)
/// </summary>
/// <param name="HostNameOrIp">主机名称或者IP地址</param>
/// <param name="port">端口</param>
/// <param name="timeOut">超时时间</param>
/// <returns>返回布尔类型</returns>
public static bool IsHostAlive(string HostNameOrIp, int? port, int? timeOut)
{
TcpClient tc = new TcpClient();
tc.SendTimeout = timeOut ?? 5000;
tc.ReceiveTimeout = timeOut ?? 5000;
bool isAlive;
try
{
tc.Connect(HostNameOrIp, port ?? 80);
isAlive = true;
}
catch
{
isAlive = false;
}
finally
{
tc.Close();
}
return isAlive;
}
}
public class TcpClientConnector
{
/// <summary>
/// 在指定时间内尝试连接指定主机上的指定端口。 (默认端口:80,默认链接超时:5000毫秒)
/// </summary>
/// <param name= "hostname ">要连接到的远程主机的 DNS 名。</param>
/// <param name= "port ">要连接到的远程主机的端口号。 </param>
/// <param name= "millisecondsTimeout ">要等待的毫秒数,或 -1 表示无限期等待。</param>
/// <returns>已连接的一个 TcpClient 实例。</returns>
public static TcpClient Connect(string hostname, int? port, int? millisecondsTimeout)
{
ConnectorState cs = new ConnectorState();
cs.Hostname = hostname;
cs.Port = port ?? 80;
ThreadPool.QueueUserWorkItem(new WaitCallback(ConnectThreaded), cs);
if (cs.Completed.WaitOne(millisecondsTimeout ?? 5000, false))
{
if (cs.TcpClient != null) return cs.TcpClient;
return null;
//throw cs.Exception;
}
else
{
cs.Abort();
return null;
//throw new SocketException(11001); // cannot connect
}
}
private static void ConnectThreaded(object state)
{
ConnectorState cs = (ConnectorState)state;
cs.Thread = Thread.CurrentThread;
try
{
TcpClient tc = new TcpClient(cs.Hostname, cs.Port);
if (cs.Aborted)
{
try { tc.GetStream().Close(); }
catch { }
try { tc.Close(); }
catch { }
}
else
{
cs.TcpClient = tc;
cs.Completed.Set();
}
}
catch (Exception e)
{
cs.Exception = e;
cs.Completed.Set();
}
}
private class ConnectorState
{
public string Hostname;
public int Port;
public volatile Thread Thread;
public readonly ManualResetEvent Completed = new ManualResetEvent(false);
public volatile TcpClient TcpClient;
public volatile Exception Exception;
public volatile bool Aborted;
public void Abort()
{
if (Aborted != true)
{
Aborted = true;
try { Thread.Abort(); }
catch { }
}
}
}
}
}
使用方法:Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net.Sockets;
namespace VvxT.Web
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
bool IsConnected = Internet.IsConnected();
bool IsAOLAlive = Internet.IsAOLAlive();
DateTime oldTime1 = DateTime.Now;
bool IsDestinationAlive = Internet.IsDestinationAlive("cn.yahoo.com");
DateTime newTime1 = DateTime.Now;
TimeSpan ts1 = newTime1 - oldTime1;
bool IsLanAlive = Internet.IsLanAlive();
bool IsWanAlive = Internet.IsWanAlive();
DateTime oldTime2 = DateTime.Now;
//bool IsHostAlive = Internet.IsHostAlive("hk.yahoo.com", null, null);//不推荐使用(无法实际控制超时时间)
bool IsHostAlive;
TcpClient tc = TcpClientConnector.Connect("hk.yahoo.com", null, null);//推荐使用(采用线程池强行中断超时时间)
try
{
if (tc != null)
{
tc.GetStream().Close();
tc.Close();
IsHostAlive = true;
}
else
IsHostAlive = false;
}
catch { IsHostAlive = false; }
DateTime newTime2 = DateTime.Now;
TimeSpan ts2 = newTime2 - oldTime2;
Response.Write("Connect:" + IsConnected + "<br />");
Response.Write("Lan:" + IsLanAlive + "<br />");
Response.Write("Wan:" + IsWanAlive + "<br />");
Response.Write("Aol:" + IsAOLAlive + "<br />");
Response.Write("Sip(cn.yahoo.com):" + IsDestinationAlive + " 耗时:" + ts1.TotalMilliseconds + "<br />");
Response.Write("TcpClient(hk.yahoo.com):" + IsHostAlive + " 耗时:" + ts2.TotalMilliseconds + "<br />");
}
}
}
运行效果:
Connect:True
Lan:True
Wan:True
Aol:True
Sip(cn.yahoo.com):True 耗时:265.625
TcpClient(hk.yahoo.com):False 耗时:5000
当然,以上类库也可以在C#windows程序中使用。