热门标签 | HotTags
当前位置:  开发笔记 > IOS > 正文

.NET中应用程序内共享UdpClient联机的实现方法

本篇文章介绍了,.NET中应用程序内共享UdpClient联机的实现方法。需要的朋友参考下

原始码下载: MutualUdpClientSample_jb51net.rar

 

在开发与远程设备通讯的系统时,为了提高数据传输的效率,常常会选择UDP这个通讯协议来作为数据传输的媒介。而 .NET framework中所提供的UdpClient对象,可以帮助开发人员依照系统需求开启UDP套接字点,快速建立UDP联机来提供与远程设备通讯的功能。

 

 

这个系统架构下当增加一个不同种类的远程设备时,必须要提供一个不同的UDP套接字点,才能用来提供与不同种类远程设备通讯的功能,在远程设备种类越来越多时,系统所需要的UDP套接字点就会依照远程设备种类而增加。

 

 

在远程设备种类越来越多的情景中,为了网络管理考虑会限制系统与远程设备通讯时,必须统一使用同一个UDP套接字点来与远程设备通讯,再由封包内容、或是IP地址去判断实际连接的远程设备为何。

代码如下:

class Program
{
    static void Main(string[] args)
    {
        // Receiver
        UdpClient udpClientA = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

        UdpClient udpClientB = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));
    }
}

依照系统需求开发人员可能写出上列的程序代码,直接建立两个UdpClient对象来开启同一个UDP套接字点。这段程序代码内容可以通过编译程序的检查,但在按下执行之后,就会在Visual Studio之中看到SocketException的例外通知,用来告知开发人员同一个套接字点只能被开启一次,使用两个UdpClient来开启同一个套接字点是无法执行的。

 

有涉略过Design pattern的开发人员,在遇到资源对象只能有一个实体的情景,会想到套用Singleton Pattern来提供资源对象共享的功能。系统中UdpClient对象所开启的UDP套接字点,就是属于这种只能由一个对象所开启的资源,这个情景中在UdpClient对象上套用Singleton Pattern看起来会是个不错的选择。

代码如下:

class Program
{
    // Singleton
    private static UdpClient _udpClientInstance = null;

    private static UdpClient UdpClientInstance
    {
        get
        {
            if (_udpClientInstance == null)
            {
                _udpClientInstance = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));
            }
            return _udpClientInstance;
        }
    }

 
    // Main
    static void Main(string[] args)
    {
        // Receiver
        UdpClient udpClientA = Program.UdpClientInstance;

        UdpClient udpClientB = Program.UdpClientInstance;

        // Transmiter
        UdpClient transmiter = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));

 
        // Send
        transmiter.Send(new byte[] { 55 }, 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

 
        // Receive
        byte[] packet = null;
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);

        packet = udpClientA.Receive(ref remoteEndPoint);
        Console.WriteLine(string.Format("UdpClientA Receive:{0}", packet[0]));

        packet = udpClientB.Receive(ref remoteEndPoint);
        Console.WriteLine(string.Format("UdpClientB Receive:{0}", packet[0]));

        // End
        Console.ReadLine();

        // Close
        transmiter.Close();
        udpClientB.Close();
        udpClientA.Close();
    }
}

将Singleton Pattern套用在系统内所使用的UdpClient物件上,可以写出上列的程序代码,系统内所使用的UdpClient对象都是取用到系统内一个静态存放的共享UdpClient对象。这段程序代码内容可以通过编译程序的检查,并且在执行时也不会出现SocketException的例外通知,因为套用Singleton Pattern让系统内只会开启UDP套接字点一次。

 

但进阶一点去思考UdpClient对象的封包接收功能,UdpClient对象中提供Receive方法来等待、接收远程设备传送的数据封包,收到数据封包之后再次执行Receive方法会继续等待、接收下一个数据封包。也就是说一个远程设备传送的数据封包,UdpClient只能透过Receive方法取得一次,在系统内共享同UdpClient对象,没有办法共享Receive方法所取得的数据封包。

 

观察上列范例的执行结果,可以发现在范例中由transmiter所传送的资料封包,在被UdpClientA透过Receive方法接收之后,UdpClientB无法接收到这个远程传送的数据封包,这也就验证范例中将Singleton Pattern套用在系统内所使用UdpClient上的方式,会发生了无法共享数据封包的问题。

 

 

为了提供系统使用同一个UDP套接字点来与远程设备通讯,再由封包内容、或是IP地址去判断实际连接的远程设备为何的功能。笔者设计一个名为MutualUdpClient的解决方案,用来在系统内共享UDP通讯联机并且共享远程设备传送的数据封包。

 

在MutualUdpClient这个解决方案中,套用先前部落格中所发表的Singleton Pool模式,套用这个模式让系统能够共享UdpClient联机,并且在有系统对象使用UdpClient联机时就开启共享UDP通讯联机,而在所有系统对象都不需要使用UdpClient联机才真正去关闭这个共享的UDP通讯联机。

 

套用Singleton Pool模式解决了共享UdpClient联机的功能,接着在MutualUdpClient这个解决方案中,为了共享远程设备传送的数据封包,在UdpClient与MutualUdpClient之间加入了一个RouteUdpClient对象。

 

RouteUdpClient对象是一个主动式的对象,在被建立之后会开启一条独立的线程,不断的接收UdpClient所接收到的数据封包,并且将接收到数据封包透过事件的方式通知每个MutualUdpClient,经由这样的流程就可以将远程设备所传送的数据封包,在每个MutualUdpClient之间共享。

 

而MutualUdpClient对象在收到RouteUdpClient所提供的数据封包时,会先将数据封包暂存在一个队列里,并且在MutualUdpClient对象的Receive方法被呼叫时,再从队列取出数据封包并且回传给呼叫端,用以将远程设备传送的数据封包提供给呼叫端做后续的处理。经由这样的方式,每个系统中所建立的MutualUdpClient对象就可以透过Receive方法取得,每个远程设备传送的数据封包。

 

*这边要特别一提的是,MutualUdpClient对象不选择事件方式来提供数据封包而采用Receive方法来提供,是为了让使用MutualUdpClient对象的开发人员,在使用对象的时候,能够得到与使用UdpClient一样的开发体验,用以减少开发时的学习时间。

 

 

处理完共享UdpClient联机、共享远程设备传送的资料封包之后,还要处理一下传送数据封包到远程设备的功能。在MutualUdpClient之中,对于传送数据封包到远程设备并没有特殊需求,所以直接使用UdpClient的Send功能就可以完成将数据封包传送到远程设备的功能。

代码如下:

class Program
{
    static void Main(string[] args)
    {
        // Receiver
        MutualUdpClient udpClientA = new MutualUdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

        MutualUdpClient udpClientB = new MutualUdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

        // Transmiter
        UdpClient transmiter = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9999));

 
        // Send
        transmiter.Send(new byte[] { 55 }, 1, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));

 
        // Receive
        byte[] packet = null;
        IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);

        packet = udpClientA.Receive(ref remoteEndPoint);
        Console.WriteLine(string.Format("UdpClientA Receive:{0}", packet[0]));

        packet = udpClientB.Receive(ref remoteEndPoint);
        Console.WriteLine(string.Format("UdpClientB Receive:{0}", packet[0]));

        // End
        Console.ReadLine();

        // Close
        transmiter.Close();
        udpClientB.Close();
        udpClientA.Close();
    }
}

上列程序代码示范如何在系统中使用MutualUdpClient对象,在范例中可以看到程序代码中直接建立了两个相同UDP端点的MutualUdpClient对象,并且可以正常的执行不会出现SocketException的例外通知。而远程设备transmiter所传送的数据封包,在被UdpClientA透过Receive方法接收之后,UdpClientB依然可以透过Receive方法接收同一个资料,这也就验证了MutualUdpClient对象提供了共享通讯联机、共享数据封包的功能。

 

原始码下载: MutualUdpClientSample_jb51net.rar


推荐阅读
  • POCOCLibraies属于功能广泛、轻量级别的开源框架库,它拥有媲美Boost库的功能以及较小的体积广泛应用在物联网平台、工业自动化等领域。POCOCLibrai ... [详细]
  • 概述H.323是由ITU制定的通信控制协议,用于在分组交换网中提供多媒体业务。呼叫控制是其中的重要组成部分,它可用来建立点到点的媒体会话和多点间媒体会议 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 64G iPad升级到iPadOS后,发现外置存储只能在苹果自带的文件app中显示,非官方app无法直接读取外置存储的内容。用户只能先使用自带文件app将文件复制到iPad上,再用程序读取。这种限制给用户带来了不便,而且操作过程中还存在拷贝不显示进度、容易失败、不能安全弹出等问题。 ... [详细]
  • Unity3D引擎的体系结构和功能详解
    本文详细介绍了Unity3D引擎的体系结构和功能。Unity3D是一个屡获殊荣的工具,用于创建交互式3D应用程序。它由游戏引擎和编辑器组成,支持C#、Boo和JavaScript脚本编程。该引擎涵盖了声音、图形、物理和网络功能等主题。Unity编辑器具有多语言脚本编辑器和预制装配系统等特点。本文还介绍了Unity的许可证情况。Unity基本功能有限的免费,适用于PC、MAC和Web开发。其他平台或完整的功能集需要购买许可证。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
  • HSRP热备份路由器协议的应用及配置
    本文介绍了HSRP热备份路由器协议的应用及配置方法,包括设计目标、工作原理、配置命令等。通过HSRP协议,可以实现在主动路由器故障时自动切换到备份路由器,保证网络连通性。此外,还介绍了R1和R2路由器的配置方法以及Sw1和Sw2交换机的配置方法,最后还介绍了测试连通性和路由追踪的方法。 ... [详细]
  • 当google在搜索上很成功,并购youtube、发布gmail、进入手机、一统地图的时候,我们说google真伟大。当苹果在mp3领域一骑绝尘,iphone秒杀诺基亚,ipad打倒了电子 ... [详细]
  • 我一直都有记录信息的习惯,不知是从什么时候开始,大约是在工作后不久。如今还真有点庆幸从那时开始记了点东西,当然是电子版的,写 ... [详细]
  • 用了element-ui的dialog组件加上canvas来绘图,在老版本 ... [详细]
  • 交换机配置:intg100unshintvlani1ipadd192.168.56.177qstelseuser-iv4authaaaproinsshupl3qsshuserpyt ... [详细]
  • 1.webkit内核中的一些私有的meta标签,这些meta标签在开发webapp时起到非常重要的作用(1) ... [详细]
  • 1、DashAPI文档Dash是一个API文档浏览器,使用户可以使用离线功能即时搜索无数API。程序员使用Dash可访问iOS,MacOS, ... [详细]
  • 单位准备购买平板电脑(如mipad),为了进行无纸化办公, ... [详细]
  • 与.Net大师Jeffrey Richter面对面交流——TUP对话大师系列活动回顾(多图配详细文字)...
    与.Net大师JeffreyRichter面对面交流——TUP对话大师系列活动回顾(多图配文字)上周末很有幸参加了CSDN举行的TUP活动, ... [详细]
author-avatar
雇Anitamia
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有