为WCF增加UDP绑定(实践篇)

简介: 这两天忙着系统其它功能的开发,没顾上写日志。本篇所述皆围绕为WCF增加UDP绑定(储备篇)中讲到的微软示例,该示例我已上传到网盘。 上篇说道,绑定是由若干绑定元素有序组成,为WCF增加UDP绑定其实就是为绑定增加UDP传输绑定元素,最终目的是在信道栈中生成UDP传输信道。

这两天忙着系统其它功能的开发,没顾上写日志。本篇所述皆围绕为WCF增加UDP绑定(储备篇)中讲到的微软示例,该示例我已上传到网盘。

上篇说道,绑定是由若干绑定元素有序组成,为WCF增加UDP绑定其实就是为绑定增加UDP传输绑定元素,最终目的是在信道栈中生成UDP传输信道。因此我们定义一个类UdpTransportBindingElement,它继承自TransportBindingElement表明这是传输相关的绑定元素。示例中该类还实现了IPolicyExportExtension和IWsdlExportExtension接口,关于这两个接口,我知道它们的作用,但看到代码却是一头雾水,我认为要能理解这块内容首先要对WSDL相关的各种规范做一详细了解,目前我先不考虑。对这有兴趣的朋友可阅读蒋大牛的元数据架构体系全景展现以前总觉得WCF不外如是,不成想这水也太特码深了(WCF相关的概念有很多,包括ChannelDispatcher、ListenerHandler、ChannelHandler等,这些和消息传输关系不大)。 

UdpTransportBindingElement主要负责绑定管理类的创建工作,服务器端和客户端分别创建的是UdpChannelListener和UdpChannelFactory。UdpChannelFactory的实现比较简单,我们重点看UdpChannelListener实现。网上资料都有类似这么一段描述:ChannelListener负责监听消息,一旦消息抵达则使用对应的Channel接收消息。在UDP解决方案中,消息监听依赖System.Net.Sockets.Socket类,示例中调用该类的BeginReceiveFrom方法进行异步监听。

 1 void StartReceiving(object state)
 2 {
 3     Socket listenSocket = (Socket)state;
 4     IAsyncResult result = null;
 5 
 6     try
 7     {
 8         lock (ThisLock)
 9         {
10             if (base.State == CommunicationState.Opened)
11             {
12                 EndPoint dummy = CreateDummyEndPoint(listenSocket);
13                 byte[] buffer = this.bufferManager.TakeBuffer(maxMessageSize);
14                 result = listenSocket.BeginReceiveFrom(buffer, 0, buffer.Length,
15                     SocketFlags.None, ref dummy, this.onReceive, new SocketReceiveState(listenSocket, buffer));
16             }
17         }
18 
19         if (result != null && result.CompletedSynchronously)
20         {
21             ContinueReceiving(result, listenSocket);
22         }
23     }
24     catch (Exception e)
25     {
26         Debug.WriteLine("Error in receiving from the socket.");
27         Debug.WriteLine(e.ToString());
28     }
29 }

需要关注Socket.BeginReceiveFrom方法,MSDN有一段描述:当应用程序调用 BeginReceiveFrom 时,系统将会使用单独的线程来执行指定的回调方法,并将在 EndReceiveFrom一直阻塞Socket 读取数据或引发异常为止。但示例中有判断该方法是否同步执行的代码,因此我认为该方法并不会每次都用异步的方式来进行数据的接收,具体请看我的另一篇文章关于IAsyncResult接口的CompletedSynchronously属性

不出意外,当数据抵达后采用Socket.EndReceiveFrom获取。我看到这里的时候觉得有点不对劲,不是说“ChannelListener负责监听消息,一旦消息抵达则使用对应的Channel接收消息”吗?既然ChannelListener都把数据接收完成了,还要Channel何用。此处似乎Channel真的只是走个过场,它存在的意义只是因为WCF框架需要它。所以我们还是需要将已接收的消息从ChannelListener传递给Channel,于是我翻看代码,希望找到一个event,在消息接收完毕后触发,以便Channel能实时得到消息可用的信号,结果没找到哪怕一个event的声明,于是我苦恼了。

 1 public interface IInputChannel : IChannel, ICommunicationObject
 2 {
 3     EndpointAddress LocalAddress { get; }
 4 
 5     IAsyncResult BeginReceive(AsyncCallback callback, object state);
 6     IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state);
 7     IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state);
 8     IAsyncResult BeginWaitForMessage(TimeSpan timeout, AsyncCallback callback, object state);
 9     Message EndReceive(IAsyncResult result);
10     bool EndTryReceive(IAsyncResult result, out Message message);
11     bool EndWaitForMessage(IAsyncResult result);
12     Message Receive();
13     Message Receive(TimeSpan timeout);
14     bool TryReceive(TimeSpan timeout, out Message message);
15     bool WaitForMessage(TimeSpan timeout);
16 }

从IInputChannel的定义可以看到,什么时候接收消息,什么时候等待,是不可控的,因为这些方法可以外部调用(一般是WCF框架自己调用)。简单地说,就是IInputChannel本身获取消息采用的是拉模式,而非推模式。为什么WCF框架不使用event模式(推模式)呢,我没有深入研究过,有知道的朋友还望赐教。这些方法调用时间不知,但若有可用消息时,不论何时调用Receive方法,我们都应该返回正确的Message,换句话说,从消息抵达到获取消息,可能有个时间差,这段时间内,消息数据不能丢失,于是我们应该有个临时存储消息数据的地方。考虑到消息数量和处理顺序,先入先出队列是个不错的选择。不出所料,示例中有个InputQueue类,该类相当复杂,不过万变不离其宗,UdpChannelListener将接收到的消息存入InputQueue,UdpInputChannel从InuptQueue中Receive消息。弄清楚这个,我便释然了。

上述模式只是实现消息从ChannelListener到Channel传递的其中一种方式,只要按规范实现WCF框架提供的关键接口,我们可以使用能想到的任何方式,比如使用event将消息接收工作转移到Channel类(更符合WCF对Channel的职责说明),当然接收到的消息仍旧需要用Receive方法去某个地方读取,因此消息的临时存储仍然必不可少。

由于最近比较忙,就先写到这里吧。示例中最核心的就是ChannelListener、InputQueue和AsyncResult类,AsyncResult类的作用也在关于IAsyncResult接口的CompletedSynchronously属性中有过阐述。若是全面铺开就太多了,有兴趣的朋友可以下载代码自己研究,有什么心得体会欢迎一起讨论。

注意用4G上网:这个地址是由网络中的GGSN或PGW分配的,是一个私网地址,但经过Gi防火墙会转换成公网IP再访问Internet。这样的话,手机侧看到的就是一个私网地址,而在互联网看来(比如站在微信服务器的角度来看),手机还有一个对应的公网IP。

 

转载请注明本文出处:http://www.cnblogs.com/newton/archive/2012/11/29/2793931.html

目录
相关文章
|
Python
145 python网络编程 - UDP绑定信息
145 python网络编程 - UDP绑定信息
59 0
|
7月前
|
网络协议
TCP和UDP可以绑定同样的端口吗?
TCP和UDP可以绑定同样的端口吗?
|
7月前
|
域名解析 网络协议 前端开发
|
Python
【从零学习python 】74. UDP网络程序:端口问题与绑定信息详解
【从零学习python 】74. UDP网络程序:端口问题与绑定信息详解
227 0
|
运维 网络协议 应用服务中间件
C/S UDP通信实践踩坑记录与对于ICMP的进一步认识
C/S UDP通信实践踩坑记录与对于ICMP的进一步认识
145 0
|
网络协议 安全 Windows
WCF如何绑定netTcpBinding寄宿到控制台应用程序详解
新建一个WCF服务类库项目,在其中添加两个WCF服务:GameService,PlayerService
WCF如何绑定netTcpBinding寄宿到控制台应用程序详解
|
网络协议
WCF绑定的选择
版权声明:欢迎评论和转载,转载请注明来源。 https://blog.csdn.net/zy332719794/article/details/8593924 格式与编码 每种标准绑定使用的传输协议与编码格式都不相同,如表1-1 所示。
619 0
|
网络协议 网络架构 安全
为WCF增加UDP绑定(储备篇)
日前我开发的服装DRP需要用到即时通信方面的技术,比如当下级店铺开出零售单时上级机构能实时收到XX店铺XX时XX分卖出XX款衣服X件之类的信息,当然在上级发货时,店铺里也能收到已经发货的提醒。即时通信技术能运用到DRP系统的很多方面,若深入下去,甚至可以开发一个系统内部的通讯模块,类似于QQ。
1014 0
|
网络协议
WCF绑定类型选择
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chinahuyong/article/details/6070364     WCF绑定类型选择     发布日期:2010年12月10日星期五 作者:EricHu     在开发WCF程序时,如何选择一个适合的绑定对于消息传输的可靠性,传输模式是否跨进程、主机、网络,传输模式的支持、安全性、性能等方面有着重要的影响。
818 0
|
XML 安全 网络协议
WCF入门(一)——终结点,地址,绑定(1)
运行WCF服务 这里通过自宿主方式self-host来运行wcf服务。 公开终结点Endpoint,终结点由ServiceEndpoint 类来实现。它有很多的成员。其中要用到的是所说的ABC。 Address,Binding,Contract,地址,绑定,契约。
1040 0