转眼你已经学了三天的wcf了,是不是很好奇wcf在传输层上面到底传递的是个什么鸟毛东西呢???应该有人知道是soap,那soap这叼毛长得是什么

样呢?这一篇我们来揭开答案。。。

一:soap到底长成什么样子

  为了能看清soap长的啥样,我可以用强大的Fiddler来监视一下,突然好激动啊!!!

1.Server

         static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(HomeService), new Uri("http://192.168.1.105:19200")); host.AddServiceEndpoint(typeof(IHomeService), new BasicHttpBinding(), "HomeServie"); //公布元数据
host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true }); host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); host.Open(); Console.WriteLine("服务已经开启。。。"); Console.Read();
}

2.Client

             ChannelFactory<IHomeService> factory = new ChannelFactory<IHomeService>(new BasicHttpBinding(), new EndpointAddress("http://192.168.1.105:19200/HomeServie"));

             var client = factory.CreateChannel();

             client.Update("王八蛋");

现在我想你大概看清楚了这玩意是个么样子,一个建立在xml上面的一种消息格式,根元素是envelope,我知道这叼毛翻译过来就是“信封”,所以就有了”封头“

和”封体”,就是s:Header 和 s:Body,从这个soap中你可以看到它忽略了header,然后我们继续往下看,还记得Update的意思吗???如果你读懂了上一篇,

你应该知道这是一个Action,也就是所谓的input消息。与之对应的就是UpdateResponse这个output消息,对吧,还记得xmlns="http://tempuri.org/">吗?

它就是IHomeService的默认命名空间,对吧。。。

下一个我们关注的是Update这个Action中的<str>这个,你也看得到,这个就是上图中Update方法中的str参数,最后我们来看一下UpdateResponse中

的<UpdateResult xmlns:a="http://schemas.datacontract.org/2004/07/MyService,不知道你是否还记得它就是WSDL中关于Student的XSD结

构,看下图:

好了,wcf中的soap结构我们也大概了解了一下,不知道有没有引发你对soap更深入的思考呢???

二:对soap的更深入思考

  通过fiddler观察,你应该也明白了,不管是客户端还是服务端,wcf的高层封装都是仅仅拿出了Envelope中的body节点,而其他节点对我们来说好像并

没有什么卵用,比如我说的Header节点,这么说来,Header是不是有点浪费呢???那下面有一个问题来了,wcf在底层用什么来构造消息的呢???下面

我们大概找下client端的源码。。。

通过上面的图,你现在应该也知道了在.net中其实tmd的就是message构造的,所以我想告诉你的是:既然wcf在底层也是用message来构造的,何不我自己

就来构造message消息呢???岂不美哉???这样我就可以随意操作message,对吧。。。不然wcf这个高层封装的叼毛,对我来说就是一种束缚。。。因

为我已经知道了service公布的wsdl,所以我可以轻松构造message。。。

三:用message来调用Server端

 废话不多说,构造message你一定要知道下图中的三点:(input这个Action,契约方式 和 服务地址)。

好了,下面我先来构造数据契约,指定服务契约的命名空间 和 Action在Soap中的名称

     [DataContract(Namespace = "http://tempuri.org/", Name = "Update")]
class Test
{
[DataMember]
public string str { get; set; }
}

然后,我把这个数据契约塞到envelope中的body中,如下:

             BasicHttpBinding bingding = new BasicHttpBinding();

             BindingParameterCollection param = new BindingParameterCollection();

             var u = new Test() { str = "王八蛋" };

             Message request = Message.CreateMessage(MessageVersion.Soap11, "http://tempuri.org/IHomeService/Update", u);

             IChannelFactory<IRequestChannel> factory = bingding.BuildChannelFactory<IRequestChannel>(param);

             factory.Open();

             IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://192.168.1.105:19200/HomeServie"));

             channel.Open();

             var result = channel.Request(request);

             channel.Close();

             factory.Close();

接下来,我们跑起来看一下,效果咋样。。。

看没看到,这个就是我手工构造的Message,是不是太帅了。。。哈哈,太帅的应该在后面,刚才也说了,既然大家玩的都是Message,而你这个几把wcf却仅仅把

我的message.body拿出来了,那干脆我直接在契约方法中加message岂不是更好么???自由操作Message还有个什么好处呢??当然啦,我可以在Message的

Header中加一些参数token,client的ip地址,client的身份,client的时间等等这些统计信息,对吧。。。这样才是最帅的,好了,说干就干,我们修改下server端的

契约方法,只用来接受Message。

server端:

     public class HomeService : IHomeService
{
public Message Update(Message message)
{
var header = message.Headers; var ip = header.GetHeader<string>("ip", string.Empty); var currentTime = header.GetHeader<string>("currenttime", string.Empty); //这个就是牛逼的 统计信息。。。
Console.WriteLine("客户端的IP=" + ip + " 当前时间=" + currentTime); return Message.CreateMessage(message.Version, message.Headers.Action + "Response", "等我吃完肯德基,再打死你这个傻逼!!!");
}
}

client端:

 namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
BasicHttpBinding bingding = new BasicHttpBinding(); BindingParameterCollection param = new BindingParameterCollection(); var u = new Test() { str = "王八蛋" }; Message request = Message.CreateMessage(MessageVersion.Soap11, "http://tempuri.org/IHomeService/Update", u); //在header中追加ip信息
request.Headers.Add(MessageHeader.CreateHeader("ip", string.Empty, Dns.GetHostByName(Dns.GetHostName()).AddressList[].ToString()));
request.Headers.Add(MessageHeader.CreateHeader("currenttime", string.Empty, DateTime.Now)); IChannelFactory<IRequestChannel> factory = bingding.BuildChannelFactory<IRequestChannel>(param); factory.Open(); IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://192.168.1.105:19200/HomeServie")); channel.Open(); var result = channel.Request(request); channel.Close(); factory.Close();
}
} [DataContract(Namespace = "http://tempuri.org/", Name = "Update")]
class Test
{
[DataMember]
public string str { get; set; }
}
}

然后我们用Fiddler监视一下结果:

现在一切都如我所愿,好了,我想你也大概明白了这个神奇的message,也不要忘了它就是wcf的基本通信单元,我要去吃肯德基了。。。。。。

[转]十五天精通WCF——第四天 你一定要明白的通信单元Message的更多相关文章

  1. 十五天精通WCF——第四天 你一定要明白的通信单元Message

    转眼你已经学了三天的wcf了,是不是很好奇wcf在传输层上面到底传递的是个什么鸟毛东西呢???应该有人知道是soap,那soap这叼毛长得是什么 样呢?这一篇我们来揭开答案... 一:soap到底长成 ...

  2. 十五天精通WCF——第六天 你必须要了解的3种通信模式

    wcf已经说到第六天了,居然还没有说到这玩意有几种通信模式,惭愧惭愧,不过很简单啦,单向,请求-响应,双工模式,其中的第二种“请求-响应“ 模式,这个大家不用动脑子都清楚,这一篇我大概来分析下. 一: ...

  3. [转]十五天精通WCF——第六天 你必须要了解的3种通信模式

    wcf已经说到第六天了,居然还没有说到这玩意有几种通信模式,惭愧惭愧,不过很简单啦,单向,请求-响应,双工模式,其中的第二种“请求-响应“ 模式,这个大家不用动脑子都清楚,这一篇我大概来分析下. 一: ...

  4. 十五天精通WCF——第十三天 用WCF来玩Rest

    在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换, 牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议, ...

  5. [转]十五天精通WCF——第十三天 用WCF来玩Rest

    在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换, 牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议, ...

  6. 十五天精通WCF——第十四天 一起聊聊FaultException

     我们在玩web编程的时候,可能你会不经意的见到一些http500的错误,我想你应该不会陌生的,原因你应该也知道,服务器异常嘛, 这时候clr会把这个未处理的异常抛给iis并且包装成http500的错 ...

  7. [转]十五天精通WCF——第十四天 一起聊聊FaultException

     我们在玩web编程的时候,可能你会不经意的见到一些http500的错误,我想你应该不会陌生的,原因你应该也知道,服务器异常嘛, 这时候clr会把这个未处理的异常抛给iis并且包装成http500的错 ...

  8. 十五天精通WCF——第一天 三种Binding让你KO80%的业务

    转眼wcf技术已经出现很多年了,也在.net界混的风生水起,同时.net也是一个高度封装的框架,作为在wcf食物链最顶端的我们所能做的任务已经简单的不能再简单了, 再简单的话马路上的大妈也能写wcf了 ...

  9. 十五天精通WCF——第七天 Close和Abort到底该怎么用才对得起观众

    一:文起缘由 写这一篇的目的源自于最近看同事在写wcf的时候,用特别感觉繁琐而且云里雾里的嵌套try catch来防止client抛出异常,特别感觉奇怪,就比如下面的代码. public void S ...

随机推荐

  1. 一个thinkphhp的聊天类,感觉还可以

    <?phpnamespace Common\Controller;use Think\Controller;class HxController extends Controller{ /** ...

  2. Akka源码分析-Actor创建(续)

    在上一遍博客中,我们已经分析了actor创建的大致过程,但只是涉及到了Dipatcher/Mailbox/ActorCell/InternalActorRef等对象的创建,并没有介绍我们自定义的继承A ...

  3. SQL数据库还原的二种方式和区别

    1.数据库还原 在SQL中,直接选择选择“还原数据库”:选中.bak 文件即可. 2.生成脚本 新建同样的DB名字,在SQL打开脚本,执行脚本语言.数据库里面就会自动填充内容.

  4. 配置Oracle数据库的开机自启动

    每当数据库服务器重启后,都要重新启动数据库的监听和实例,特别是在服务器断电重启.例行维护性的场景下.能否像Windows服务器一样,让实例和监听随着服务的启动而启动呢?答案当然是肯定的,我们可以利用O ...

  5. OFDM同步算法之Minn算法

    minn算法代码 算法原理 训练序列结构 T=[B B -B -B],其中B表示由长度为N/4的复伪随机序列PN,ifft变换得到的符号序列 (原文解释):B represent samples of ...

  6. drupal-使用hook_preprocess_field在paragraph的accordion中添加自定义数据

    描述:我的accordion类型原先只有两个字段,分别是title和content.显示在页面上会默认隐藏其内容,点击“+”会显示内容.然而现在有一个新需求,就是加一个开关使编辑内容者可以选择默认“展 ...

  7. Canvas——基本入门

    基本概念 1.canvas 是 HTML5 提供的一个用于展示绘图效果的标签. canvas 原意画布, 帆布. 在 HTML 页面中用于展示绘图效果. 最早 canvas 是苹果提出的一个方案, 今 ...

  8. SQL基本操作——存储过程

    存储过程类似于C#中的方法. --创建存储过程 create proc usp_TwoNumberAdd @num1 int, @num2 int as begin select @num1+@num ...

  9. [Windows Server 2008] Apache+PHP安全设置

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:Win2008 ...

  10. MyBatis入门2_增删改查+数据库字段和实体字段不一致情况

    本文为博主辛苦总结,希望自己以后返回来看的时候理解更深刻,也希望可以起到帮助初学者的作用. 转载请注明 出自 : luogg的博客园 谢谢配合! 当数据库字段和实体bean中属性不一致时 之前数据库P ...