WCF如何克服HTTP传输协议的局限提供对不同消息传输模式的实现

WCF采用消息作为通信的唯一手段,它支持不同的消息交换模式(MEP:Message Exchange Pattern),比较典型的有以下三种MEP:One-Way、Request/Reply和Duplex。消息会被WCF的信道层发送到传输层,并通过相应的传输协议发送到目的地。对于TCP协议来说,其本身就能提供一个双工通道,所以能够对以上三种MEP原生的支持。而HTTP协议,大家都知道它天生就基于Request/Reply模式的,那么它是如何能够突破自己的局限,为One-Way和Duplex消息交换模式提供支持呢?

一、HTTP如何实现One-Way消息交换模式?

One-Way模式是最简单的消息交换模式,又称为发送/遗忘(Send/Forget)或者数据报模式(Datagram)。One-Way模式基于从一个源到一个或者多个目的地的单向消息传输。如右图所示,在One-Way模式下,消息的发送方将消息发送到接收方,并不希望收到对象的回复。数据报模式具有一些变型,比较典型的包括以下一些消息交换的方式: 单目的地模式(一个消息的发送方将消息发送给单一的接收方)、多投模式(一个消息发送方将消息发送给一系列预定义的接收方)和广播模式(和多投模式相似,只是接收方的范围更加宽泛)。One-Way模式一般采用异步的消息发送方式,并不希望接收到对方的回复消息,在个别情况下甚至不关心消息能否正常地被接收。

但是,关于HTTP有一点必须有一个清醒的认识,那就是HTTP只能采用Request/Reply模式进行工作,这是由其协议本身的实现决定的。那么,当我们采用基于HTTP的绑定(BasicHttpBinding、WSHttpBinding和WS2007HttpBinding等)调用One-Way服务操作的时候,传输层(HTTP Transport)是如何工作的呢?实际上很简单:客户端照常向服务端发送基于SOAP的HTTP Request,服务端在接收到清之后,会返回一个状态为202(表示成功请求成功接受)的空HTTP Response。整个请求回复过程如左图所示。

实际上我们可以利用一些消息拦截工具,截获客户端和服务端往来的消息来分析它们之间真正采用的消息交换方式,在这里我们采用的是Fiddler这么一个广受大家喜爱的HTTP Debug Proxy。现在,我们需要通过Fiddler探测进行基于One-way服务操作调用采用的消息交换方式,假设服务契约定义如下:

using System.ServiceModel;
namespace Artech.MessageInspection.Sender
{
    [ServiceContract(Namespace="http://www.artech.com/")]
    interface ICalculator
    {
        [OperationContract(IsOneWay = true)]
        void Add(double x, double y);
    }
}

服务实现、服务寄宿和服务调用的相关代码我们就省了。现在,客户端通过创建的服务代理,简单地调用Add(1,2)这么一个简单的服务操作。下图反映了Fiddler对该过程进行拦截得到的截图,可以看到整个过程还是经典的Request/Reply方法,而回复的是一个空的HttpResponse。下面是整个HttpResponse的内容:

HTTP/1.1 202 Accepted
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 20 Apr 2010 14:31:36 GMT

二、 HTTP如何实现Duplex消息交换模式?

如果采用Duplex的消息交换模式,在进行消息交换过程中,任何一方都可以向对方发送消息,如右图所示。双工通信使服务端回调客户端操作成为可能。比较典型Duplex通信是我们熟悉的订阅/发布模式。订阅/发布模式下的消息交换双方的角色从传统的发送方和接收方变成了订阅方和发布方。订阅方向发布方发送订阅消息定于某一主题进行订阅,发布方接收到订阅消息后将订阅方添加到订阅列表之中。主题发布的时候,发布方提取当前主题的所有订阅方,对它们进行消息广播。

消息的交换依赖于网络传递,不同的网络传输协议对双工通信具有不同的支持方式。对于TCP协议来说,其协议本身就是全双工的网络通信协议,所以能够提供双工通信原生的支持。但是对于HTTP来说,它本身就是简单的基于请求/回复的网络协议,是不支持双工通信的。WCF通过WsDualHttpBinding实现了基于HTTP协议的双工通信,实际上是采用了两个HTTP通道实现的。 Duplex消息交换模式实际上是由两个简单模式(One-Way或者Request/Reply)组合而成的。WCF通过双工通信实现了服务端对客户端的回调。假设客户端采用One-way的方式调用服务,而服务端同样以One-Way的方式对客户端进行回调。在这个过程中,正常的服务调用和回调实现上是在不同的HTTP通道中进行的。从消息交换的角度讲,客户端调用服务端和服务端对客户端进行回调,本质上是一样的。所以,从HTTP传输层看,真正的消息交换方式如左图所示。如果同样采用Fiddler这样的工具,你会看到对于服务的正常调用是一个HttpRequest/HttpREsponse(Status:202),回调也对应着一个HttpRequest/HttpREsponse(Status:202),只是两者的方向相反而已。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据之美

shell 学习笔记(19)

声明:转载需署名出处,严禁用于商业用途! 1801.关于 nohup 后台运行的问题: nohup就是拒绝hup信号,没什么其他用途, 如...

25650
来自专栏零基础使用Django2.0.1打造在线教育网站

零基础使用Django2.0.1打造在线教育网站(十四):用户密码找回

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

35410
来自专栏Rovo89

Unix/Linux常用的命令

19950
来自专栏前端杂货铺

服务端事件EventSource揭秘

服务端推 服务端推,指的是由服务器主动的向客户端发送消息(响应)。在应用层的HTTP协议实现中,“请求-响应”是一个round trip,它的起点来自客户端,因...

33950
来自专栏木头编程 - moTzxx

CentOS7 ab压力测试安装与解释

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

30520
来自专栏木头编程 - moTzxx

ThinkPHP 框架下支付宝支付

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

45930
来自专栏平凡文摘

Java程序员最常用的Linux命令

25540
来自专栏编程

小白爬虫之爬虫快跑

使用多线程时好像在目录切换的问题上存在问题,可以给线程加个锁试试 Hello 大家好!我又来了。 你是不是发现下载图片速度特别慢、难以忍受啊!对于这种问题一般解...

20080
来自专栏草根专栏

.NET Core TDD 前传: 编写易于测试的代码 -- 全局状态

全局状态, 也可以叫做应用程序状态, 它是一组变量, 这些变量维护着应用程序的高级状态.

10330
来自专栏backend技术总结

微信小程序demo开发总结

github: https://github.com/tencentyun/wafer-session-server

51640

扫码关注云+社区

领取腾讯云代金券