Channel分为2种:transport信道和protocol信道。
Service和Client都有一个信道栈,由多个信道组成,其中,transport信道位于信道栈的最底层,protocol信道位于信道栈的最上层。
protocol信道用于消息交互、安全、事务、日志。
transport信道用于transport和encoder。
信道栈又被称为Binding~~娃哈哈,终于找到了共性。
信道栈至少包含一个transport和一个encoder,不一定包括protocol信道。
WFC支持3种消息交换模式:
oneway
duplex
request-reply
为此,WCF提供了10中不同的接口,统称为Channel Shapes:
其中5个:
IOutputChannel IInputChannel IDuplexChannel IRequestChannel IReplyChannel
它们是不支持Session的。于是,还有5个支持Session的接口:
IOutputSessionChannel IInputSessionChannel IDuplexSessionChannel IRequestSessionChannel IReplySessionChannel
一个一个分析:
1)OneWay
消息发送仅一个方向:Client->Server
Client不需要立刻获得server返回的response,client只需要知道消息已经被发送出去了。消息发送的同时,本次通信即宣告结束。
OneWay由IOutputChannel和IInputChannel组成,前者用来发消息,后者用于收消息:
2.Duplex
说白了,就是由2个oneway组成的,汇聚在一个接口中:IDuplexChannel
3.Request-Reply
每一个request都对应一个response。在client发送一个request后,必须等待response返回后,才能发送另外的request。
使用了IRequestChannel和IResponseChannel接口
貌似浏览器处理HTTP request时就是按照这种方式。
有一名技术,叫做Shape Changing。大体是说,HTTP transport信道使用的是Request-Reply,而如果在HTTP上使用oneway和duplex,就必须使用Shape Changing技术。为此,我们要自定义一个新的protocol Channel,位于原有的transport channel之上。
CustomBinding binding = new CustomBinding( new OneWayBindingElement(), new TextMessageEncodingBindingElement(), new HttpTransportBindingElement());
//oneway BasicHttpBinding binding = new BasicHttpBinding(); BindingParameterCollection parameters = new BindingParameterCollection(); Message message = Message.CreateMessage(MessageVersion.Soap11, "urn:sendmessage"); IChannelFactory<IOutputChannel> factory = binding.BuildChannelFactory<IOutputChannel>(parameters); IOutputChannel channel = factory.CreateChannel(new EndpointAddress("http://localhost/sendmessage/")); channel.Send(message); channel.Close(); factory.Close(); //duplex NetTcpBinding binding = new NetTcpBinding(); BindingParameterCollection parameters = new BindingParameterCollection(); Message message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "urn:sendmessage"); IChannelFactory<IDuplexChannel> factory = binding.BuildChannelFactory<IDuplexChannel>(parameters); IDuplexChannel channel = factory.CreateChannel(new EndpointAddress("net.tcp://localhost/sendmessage/")); channel.Send(message); channel.Close(); factory.Close(); //request-reply BasicHttpBinding binding = new BasicHttpBinding(); BindingParameterCollection parameters = new BindingParameterCollection(); Message request = Message.CreateMessage(MessageVersion.Soap11, "urn:sendmessage"); IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>(parameters); IRequestChannel channel = factory.CreateChannel(new EndpointAddress("http://localhost/sendmessage/")); Message response = channel.Request(request); channel.Close(); factory.Close();