十五天精通WCF——第四天 你一定要明白的通信单元Message
转眼你已经学了三天的wcf了,是不是很好奇wcf在传输层上面到底传递的是个什么鸟毛东西呢???应该有人知道是soap,那soap这叼毛长得是什么
样呢?这一篇我们来揭开答案。。。
一:soap到底长成什么样子
为了能看清soap长的啥样,我可以用强大的Fiddler来监视一下,突然好激动啊!!!
1.Server
1 static void Main(string[] args) 2 { 3 ServiceHost host = new ServiceHost(typeof(HomeService), new Uri("http://192.168.1.105:19200")); 4 5 host.AddServiceEndpoint(typeof(IHomeService), new BasicHttpBinding(), "HomeServie"); 6 7 //公布元数据 8 host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true }); 9 10 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); 11 12 host.Open(); 13 14 Console.WriteLine("服务已经开启。。。"); 15 16 Console.Read(); 17 }
2.Client
1 ChannelFactory<IHomeService> factory = new ChannelFactory<IHomeService>(new BasicHttpBinding(), new EndpointAddress("http://192.168.1.105:19200/HomeServie")); 2 3 var client = factory.CreateChannel(); 4 5 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中的名称
1 [DataContract(Namespace = "http://tempuri.org/", Name = "Update")] 2 class Test 3 { 4 [DataMember] 5 public string str { get; set; } 6 }
然后,我把这个数据契约塞到envelope中的body中,如下:
1 BasicHttpBinding bingding = new BasicHttpBinding(); 2 3 BindingParameterCollection param = new BindingParameterCollection(); 4 5 var u = new Test() { str = "王八蛋" }; 6 7 Message request = Message.CreateMessage(MessageVersion.Soap11, "http://tempuri.org/IHomeService/Update", u); 8 9 IChannelFactory<IRequestChannel> factory = bingding.BuildChannelFactory<IRequestChannel>(param); 10 11 factory.Open(); 12 13 IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://192.168.1.105:19200/HomeServie")); 14 15 channel.Open(); 16 17 var result = channel.Request(request); 18 19 channel.Close(); 20 21 factory.Close();
接下来,我们跑起来看一下,效果咋样。。。
看没看到,这个就是我手工构造的Message,是不是太帅了。。。哈哈,太帅的应该在后面,刚才也说了,既然大家玩的都是Message,而你这个几把wcf却仅仅把
我的message.body拿出来了,那干脆我直接在契约方法中加message岂不是更好么???自由操作Message还有个什么好处呢??当然啦,我可以在Message的
Header中加一些参数token,client的ip地址,client的身份,client的时间等等这些统计信息,对吧。。。这样才是最帅的,好了,说干就干,我们修改下server端的
契约方法,只用来接受Message。
server端:
1 public class HomeService : IHomeService 2 { 3 public Message Update(Message message) 4 { 5 var header = message.Headers; 6 7 var ip = header.GetHeader<string>("ip", string.Empty); 8 9 var currentTime = header.GetHeader<string>("currenttime", string.Empty); 10 11 //这个就是牛逼的 统计信息。。。 12 Console.WriteLine("客户端的IP=" + ip + " 当前时间=" + currentTime); 13 14 return Message.CreateMessage(message.Version, message.Headers.Action + "Response", "等我吃完肯德基,再打死你这个傻逼!!!"); 15 } 16 }
client端:
1 namespace ConsoleApplication1 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 BasicHttpBinding bingding = new BasicHttpBinding(); 8 9 BindingParameterCollection param = new BindingParameterCollection(); 10 11 var u = new Test() { str = "王八蛋" }; 12 13 Message request = Message.CreateMessage(MessageVersion.Soap11, "http://tempuri.org/IHomeService/Update", u); 14 15 //在header中追加ip信息 16 request.Headers.Add(MessageHeader.CreateHeader("ip", string.Empty, Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString())); 17 request.Headers.Add(MessageHeader.CreateHeader("currenttime", string.Empty, DateTime.Now)); 18 19 IChannelFactory<IRequestChannel> factory = bingding.BuildChannelFactory<IRequestChannel>(param); 20 21 factory.Open(); 22 23 IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://192.168.1.105:19200/HomeServie")); 24 25 channel.Open(); 26 27 var result = channel.Request(request); 28 29 channel.Close(); 30 31 factory.Close(); 32 } 33 } 34 35 [DataContract(Namespace = "http://tempuri.org/", Name = "Update")] 36 class Test 37 { 38 [DataMember] 39 public string str { get; set; } 40 } 41 }
然后我们用Fiddler监视一下结果:
现在一切都如我所愿,好了,我想你也大概明白了这个神奇的message,也不要忘了它就是wcf的基本通信单元,我要去吃肯德基了。。。。。。
十五天精通WCF——第四天 你一定要明白的通信单元Message相关推荐
- 十五天精通WCF——第六天 你必须要了解的3种通信模式
十五天精通WCF--第六天 你必须要了解的3种通信模式 原文:十五天精通WCF--第六天 你必须要了解的3种通信模式 wcf已经说到第六天了,居然还没有说到这玩意有几种通信模式,惭愧惭愧,不过很简单啦 ...
- 十五天精通WCF——第十四天 一起聊聊FaultException
原文:十五天精通WCF--第十四天 一起聊聊FaultException 我们在玩web编程的时候,可能你会不经意的见到一些http500的错误,我想你应该不会陌生的,原因你应该也知道,服务器异常嘛 ...
- 十五天精通WCF——第七天 Close和Abort到底该怎么用才对得起观众
原文:十五天精通WCF--第七天 Close和Abort到底该怎么用才对得起观众 一:文起缘由 写这一篇的目的源自于最近看同事在写wcf的时候,用特别感觉繁琐而且云里雾里的嵌套try catch来防止 ...
- 十五天精通WCF——第五天 你需要了解的三个小技巧
十五天精通WCF--第五天 你需要了解的三个小技巧 原文: 十五天精通WCF--第五天 你需要了解的三个小技巧 一: 服务是端点的集合 当你在开发wcf的时候,你或许已经注意到了一个service可以 ...
- 十五天精通WCF——第十三天 用WCF来玩Rest
在我们玩wcf的时候,都会潜意识的觉得wcf就是通过soap协议交换消息的,并且可以在basic,tcp,msmq等等绑定中任意切换, 牛逼的一塌糊涂,但是呢,如果说哪一天wcf不再使用soap协议, ...
- 十五天精通WCF——第三天 client如何知道server提供的功能清单
通常我们去大保健的时候,都会找姑娘问一下这里能提供什么服务,什么价格,这时候可能姑娘会跟你口述一些服务或者提供一份服务清单,这样的话大 家就可以做到童嫂无欺,这样一份活生生的例子,在wcf中同样是一 ...
- 十五天精通WCF——第八天 对“绑定”的最后一点理解
转眼已经中断10几天没有写博客了,也不是工作太忙,正好碰到了端午节,然后最近看天津台的爱情保卫战入迷了...太好看了,一直都是回味无穷...而且 涂磊老师话说的真是tmd的经典,然后就这样耽搁了,好了 ...
- 十五天精通WCF——第十一天 如何对wcf进行全程监控
说点题外话,我们在玩asp.net的时候,都知道有一个叼毛玩意叫做"生命周期",我们可以用httpmodule在先于页面的page_load中 做一些拦截,这样做的好处有很多,比如 ...
- 十五天精通WCF——第十二天 说说wcf中的那几种序列化
转自:https://www.cnblogs.com/huangxincheng/p/4660251.html 我们都知道wcf是由信道栈组成的,在我们传输的参数走到传输信道层之前,先需要经过序列化的 ...
- 案例分析1-用Python来解决鸡兔同笼问题: 今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何? ji = 0 tu = 0 while ji <=35:tu = 35-jiif 2*ji+4*tu==94:print ('鸡:',j ...
最新文章
- IDEA创建子项目 parent标签报错
- Go 开发关键技术指南 | Go 面向失败编程 (内含超全知识大图)
- androidstudio sqlite where 条件_SQL 面试题:WHERE 和 HAVING、ON 有什么区别?
- iphone网络交互json实现
- IIS 6.0支持.SHTML
- 复制以下命令到终端中,C++然后回车即可
- 【BZOJ3223】文艺平衡树,Splay反转区间
- mysql 8创建远程访问用户以及连接mysql速度慢的解决方法
- c语言程序设计报告链表,c语言程序设计报告链表实现学生信息管理.docx
- Elasticsearch官档翻译——1 4 修改数据
- sqlserver 查找某个字符在字符串中第N次出现的位置
- 数据结构专题:树链剖分
- html倒计时代码执行操作,JS倒计时两种实现方式代码实例
- 理解什么叫“自然拼读”
- RHEL5 Oracle 11G R2 RAC 静默安装 (一) GI安装前 准备
- #第二章 数理文化的起源2.1文化概述
- 数字图像处理(冈萨雷斯版)学习笔记(6)第10章
- PM:iOS 为什么感觉比 Android 流畅?
- KinectGestures
- c语言自动输入0到1000,c语言实现输入一组数自动从大到小排列
热门文章
- 1.Entity Framework Core 5.0教程,概述和准备
- Django中使用MySQL
- linux解压压缩命令
- VirtualBox虚拟机压缩减少体积
- 就个人开发而言,Ubuntu比Debian更适合
- 见贤思齐,正式开启源码之旅
- CSDN排名规则变化略谈
- THCudaCheck FAIL file=/pytorch/aten/src/THC/THCGeneral.cpp line=405 error=11 : invalid argument
- 解决方法:Linux装完显卡驱动后分辨率显示不正常
- 如何证明人的记忆力是无限的