VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#教程 >
  • C#教程之C#教程之在 .NET 中,扫描局域网服务的实现

本站最新发布   C#从入门到精通
试听地址  
https://www.xin3721.com/eschool/CSharpxin3721/

在最近负责的项目中,需要实现这样一个需求:在客户端程序中,扫描当前机器所在网段中的所有机器上是否有某服务启动,并把所有已经启动服务的机器列出来,供用户选择,连接哪个服务。注意:这里所说的服务事实上就是在一个固定的端口监听基于 TCP 协议的请求的程序或者服务(如 WCF 服务)。

要实现这样的功能,核心的一点就是在得到当前机器同网段的所有机器的 IP 后,对每一 IP 发生 TCP 连接请求,如果请求超时或者出现其它异常,则认为没有服务,反之,如果能够正常连接,则认为服务正常。

经过基本功能的实现以及后续的重构之后,就有了本文以下的代码:一个接口和具体实现的类。需要说明的是:在下面的代码中,先提到接口,再提到具体类;而在开发过程中,则是首先创建了类,然后才提取了接口。之所以要提取接口,原因有二:一是可以支持 IoC控制反转;二是将来如果其它的同类需求,可以基于此接口创建新类而实现新需求。

回到顶部

一、接口定义

先看来一下接口:

复制代码
    /// <summary>
    /// 扫描服务
    /// </summary>
    public interface IServerScanner
    {
        /// <summary>
        /// 扫描完成
        /// </summary>
        event EventHandler<List<ConnectionResult>> OnScanComplete;

        /// <summary>
        /// 报告扫描进度
        /// </summary>
        event EventHandler<ScanProgressEventArgs> OnScanProgressChanged;

        /// <summary>
        /// 扫描端口
        /// </summary>
        int ScanPort { get; set; }

        /// <summary>
        /// 单次连接超时时长
        /// </summary>
        TimeSpan Timeout { get; set; }

        /// <summary>
        /// 返回指定的IP与端口是否能够连接上
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        bool IsConnected(IPAddress ipAddress, int port);

        /// <summary>
        /// 返回指定的IP与端口是否能够连接上
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        bool IsConnected(string ip, int port);

        /// <summary>
        /// 开始扫描

        /// </summary>
        void StartScan();
    }
复制代码

其中 Timeout 属性是控制每次连接请求超时的时长。

回到顶部

二、具体实现

再来看一下具体实现类:

 ServerScanner

 

以上代码中注释基本上已经比较详细,这里再简单提几个点:

  1. TestConnection 函数实了现核心功能,即请求给定的 IP 和端口,并返回结果;其中通过调用 IAsyncResult.AsyncWaitHandle 属性的 WaitOne 方法来实现对超时的控制;
  2. StartScan 方法中,在得到 IP 列表后,通过生成委托列表并异步调用这些委托来实现整个方法是异步的,不会阻塞 UI,而这些委托指向的方法就是 TestConnection 函数;
  3. 使用同步上下文 SynchronizationContext,可以保证调用方在原来的线程(通常是 UI 线程)上处理进度更新事件或扫描完成事件;
  4. 对于每个委托异步完成后,会执行回调方法 OnComplete,在它里面,对全局变量的操作需要加锁,以保证线程安全。
回到顶部

三、如何使用

最后来看一下如何使用,非常简单:

复制代码
        private void View_Loaded()
        {
            // 在界面 Load 事件中添加以下代码
            ServerScanner.OnScanComplete += ServerScanner_OnScanComplete;
            ServerScanner.OnScanProgressChanged += ServerScanner_OnScanProgressChanged;

            // 扫描的端口号
            ServerScanner.ScanPort = 7890;
        }

        private void StartScan()
        {
            // 开始扫描
            ServerScanner.StartScan();
        }


        private void ServerScanner_OnScanComplete(object sender, List<ConnectionResult> e)
        {
            ...
        }

        private void ServerScanner_OnScanProgressChanged(object sender, ScanProgressEventArgs e)
        {
            ...
        }
复制代码

如果你有更好的建议或意见,请留言互相交流。

 

作者:WPInfo

本文系作者原创,欢迎转载;如需转载,请注明出处

相关教程