用实例浅谈WCF通道

通道负责发送和传递消息。在WCF中有协议通道和传输通道。协议通道主要对消息进行转换、修改,来实现各种协议(安全、可靠消息、事务等)。传输通道主要通过某种传输机制(http、tcp、msmq等)来传送消息。不同功能的通道在一起组成了通道栈。通道栈至少会拥有一个传输信道和一个编码器,如,httpTransport传输通道默认使用TextMessageEncoding,这样就实现了一个通道栈。用通道编程很有socket编程的味道。了解下通道对理解WCF以及扩展WCF都是很有帮助的。

WCF中有三种消息交换模式。

数据报(IInputChannel 和IOutputChannel)(单向):消息只从客户端发送到服务端而且消息在发送过程中可能丢失。这种方式下,客户端仅需要得到一个通知来确认消息已经发送完成,消息发送完成后,本次通信就结束。

请求-响应(IRequestChannel 和 IReplyChannel)(半双工):客户端发送一请求消息后必须等待服务端返回一响应消息后才能发送下一个请求。

双工 (IDuplexChannel):消息可以从客户端或者服务器端任意一端发出。

MSDN有一示意图不错,我给整下来粘我这里了。

下面用请求-响应模式,写一程序把握下通道编程:

实体类:

using System;
using System.Runtime.Serialization;

namespace FruitModel
{
[DataContract(Namespace
="http://www.cnbolgs.com/qiuwuyu")]
public class Fruit
{
private string m_Name = string.Empty;
private string m_Price = string.Empty;
public Fruit(string name, string price)
{
m_Name
= name;
m_Price
= price;
}
[DataMember]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
[DataMember]
public string Price
{
get { return m_Price; }
set { m_Price = value; }
}
}
}

服务端:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.Text;
using FruitModel;

namespace WcfChannelHost
{
class Program
{
static void Main(string[] args)
{
//创建一文本编码http传输的自定义绑定
TextMessageEncodingBindingElement textMsgEncode = new
TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8);
CustomBinding customBinding
= new CustomBinding();
customBinding.Elements.Add(textMsgEncode);
customBinding.Elements.Add(
new HttpTransportBindingElement());
//创建通道监听器
IChannelListener<IReplyChannel> listener =
customBinding.BuildChannelListener
<IReplyChannel>(new Uri("http://localhost:8000"),
new BindingParameterCollection());
//监听消息
listener.Open();
IReplyChannel channel
= listener.AcceptChannel();
//打开接收通道
channel.Open();
Console.WriteLine(
"Listening for messages...");
//等待并接收来自通道的消息
RequestContext request = channel.ReceiveRequest();
//读取请求消息
Message message = request.RequestMessage;
Console.WriteLine(message.ToString());

Fruit fruit
= message.GetBody<Fruit>();
fruit.Price
= "4.50";
//发送响应消息
Message replyMessage = Message.CreateMessage(customBinding.MessageVersion,
"http://www.cnblogs.com/qiuwuyu", fruit);
request.Reply(replyMessage);
//释放非托管资源
message.Close();
request.Close();
channel.Close();
listener.Close();
Console.ReadLine();
}
}
}

客户端:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.Text;
using FruitModel;

namespace WcfChannelClient
{
class Program
{
static void Main(string[] args)
{
//创建一文本编码http传输的自定义绑定
TextMessageEncodingBindingElement textMsgEncode = new
TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8);
CustomBinding customBinding
= new CustomBinding();
customBinding.Elements.Add(textMsgEncode);
customBinding.Elements.Add(
new HttpTransportBindingElement());

//用customBinding构建一通道工厂
IChannelFactory<IRequestChannel> factory = customBinding.BuildChannelFactory<IRequestChannel>(
new BindingParameterCollection());
factory.Open();
//同通道工厂创建一个通道
IRequestChannel channel = factory.CreateChannel(new EndpointAddress ("http://localhost:8000"));
channel.Open();
//创建请求消息
Message requestMessage = Message.CreateMessage(customBinding.MessageVersion,
"http://www.cnbolgs.com/qiuwuyu",new Fruit("banana", "6.00"));
//发送请求消息并获取返回消息
Message replyMessage = channel.Request(requestMessage);
Console.WriteLine(
"Reply message is:");
Console.WriteLine(replyMessage.ToString());

//释放非托管资源
replyMessage.Close();
channel.Close();
factory.Close();

Console.ReadLine();
}
}
}

没有启动客户端前:

启动客户端后的服务端:

客户端:

posted @ 2011-04-19 08:38  秋无语  阅读(1411)  评论(1编辑  收藏  举报