C#获取网络链接状态的几种方法(己封装为类)

本人从事编程也几年了,一直在互联网中排徊,平时遇到问题也是baidu或google什么的,一直都没有想着去记录想法的一些技术文章,今天是元旦,老婆又刚好回家了,所以在这里就发表我的第一篇文章吧,呵呵

现在很多项目中都需要网络来支持,使网络链接检测就成为了很普遍的问题... 好了,废话就不多说了,首先这里祝大家元旦快乐!!直入主题吧!

 

Internet.cs

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/S和B/S结构,以上测试环境为WebApplication。

写的不好的请多多指教!

posted @ 2011-01-01 00:49  varvery  阅读(2603)  评论(3编辑  收藏  举报