欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-03-01 17:58:10
原始码下载: mutualudpclientsample_jb51net.rar   在开发与远程设备通讯的系统时,为了提高数据传输的效率,常常会选择ud...

原始码下载: mutualudpclientsample_jb51net.rar

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

 

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

 

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

 

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

 

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

 

在远程设备种类越来越多的情景中,为了网络管理考虑会限制系统与远程设备通讯时,必须统一使用同一个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来开启同一个套接字点是无法执行的。

.NET中应用程序内共享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上的方式,会发生了无法共享数据封包的问题。

 

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

 

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

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

 

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

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

 

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

 

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

 

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

 

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

 

.NET中应用程序内共享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对象提供了共享通讯联机、共享数据封包的功能。

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

 

原始码下载: mutualudpclientsample_jb51net.rar

上一篇: Java基础知识汇总

下一篇: