由於WCF中提供了CallbackContract屬性,所以在雙工通信中,我們可以很方便的和Server進行通信。雖然查遍了MSDN,也看過了它提供的例子,但是還是不知道怎么來使用(因為MSDN中只是給你提供了Server端的調用方法,並沒有客戶端的調用方式,所以例子沒法兒跑起來,當然也就不能夠從示例中看出CallbackContract屬性的工作方式,鄙視下,呵呵)。在這篇文章中,我要做的就是讓這個例子能夠順利地跑起來,從而了解CallbackContract的工作方式。
服務端編寫
首先,創建一個名稱為CallbackContractWCF的控制台項目,添加一個DuplexHello類作為我們的Service,具體代碼就Copy了MSDN上面的:

using System; using System.ServiceModel; using System.Threading; namespace CallbackContractWCF { [ServiceContract(Name = "SampleDuplexHello", CallbackContract = typeof(IHelloCallbackContract), SessionMode = SessionMode.Required)] public interface IDuplexHello { [OperationContract(IsOneWay = true)] void Hello(string greeting); } public interface IHelloCallbackContract { [OperationContract(IsOneWay = true)] void Reply(string responseToGreeting); } public class DuplexHello:IDuplexHello { public DuplexHello() { Console.WriteLine("Service object created: " + this.GetHashCode().ToString()); } ~DuplexHello() { Console.WriteLine("Service object distroyed: " + this.GetHashCode().ToString()); } public void Hello(string greeting) { Console.WriteLine("Caller sent: "+greeting); Console.WriteLine("Session ID: "+OperationContext.Current.SessionId); Console.WriteLine("Waiting two seconds before returning call."); Thread.Sleep(2000); IHelloCallbackContract callerProxy = OperationContext.Current.GetCallbackChannel<IHelloCallbackContract>(); string response = "Service object " + this.GetHashCode().ToString() + " received." + greeting; Console.WriteLine("Sending back: " + response); callerProxy.Reply(response); } } }
從這個類中,我們可以看到它有一個IHelloCallbackContract的接口,由於它在ServiceContract中被標記為CallbackContract = typeof(IHelloCallbackContract),所以它用於客戶端回調。意即,服務端可以通過此接口中的方法將數據發送給客戶端,客戶端只需要實現此接口,即可接收到服務端發送過來的消息。
然后是創建配置文件,請參見我的文章:基於net.tcp的WCF配置實例解析。這里我們使用的EndPoint為:net.tcp://127.0.0.1/DuplexHello,創建好App.config配置文件后,拷貝到CallbackContractWCF項目下,然后打開Program.cs文件,編碼以便讓服務端能夠啟動監聽:

using (ServiceHost host = new ServiceHost(typeof(DuplexHello))) { ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); if (smb == null) { host.Description.Behaviors.Add(new ServiceMetadataBehavior()); } //暴露MetaData,以便能夠讓SvcUtil.exe工具生成客戶端代理類和配置文件 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); host.Open(); Console.WriteLine("service listen on endpoint ..."); Console.WriteLine("Press ENTER to stop ..."); Console.ReadLine(); host.Abort(); host.Close(); }
好了,啟動服務端,我們可以看到如下界面,服務端啟動成功了:
客戶端編寫
下面開始來編寫客戶端。
首先打開SvcUtil.exe,按照文章:基於net.tcp的WCF配置實例解析 中介紹的方法,生成output.config文件和DuplexHello.cs代理類文件。
其次創建一個名稱為CallbackContractWCFClient的Windows Form Application項目,將上面的兩個文件拷貝進來,並修改output.config名稱為App.config。
然后打開ClientForm窗體,繼承自SampleDuplexHelloCallback接口(這個接口也就是服務端的IHelloCallbackContract接口的代理),然后編寫以下代碼進行數據發送和接收:

using System; using System.Windows.Forms; using System.ServiceModel; namespace CallbackContractWCFClient { public partial class ClientForm : Form, SampleDuplexHelloCallback { public ClientForm() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { InstanceContext site = new InstanceContext(this); SampleDuplexHelloClient client = new SampleDuplexHelloClient(site); string msg =" This is a Client Message sent to Server side..."; label1.Text = "Client Sent: " + msg; client.Hello(msg); } public void Reply(string responseToGreeting) { label2.Text = "Server Reply: " + responseToGreeting; } } }
這樣,我們的服務端和客戶端就寫好了,接下來運行,結果顯示如下:
服務端:
客戶端:
源碼下載