本文主要通過文件配置來講解如何編寫一個基於net.tcp的Windows Form小程序。
使用的工具
涉及的工具有:
SvcUtil.exe
WCF Service Configuration Editor
服務器端的配置步驟
首先讓我們來開始編寫服務器端,服務器端用的是Console Application。
由於我們的軟件是一個能夠通過學生ID來獲取學生姓名的小程序,所以,首先必須得有一個StudentInfo實體類:

using System.Runtime.Serialization; namespace WCFServiceGeneratedByConfig { [DataContract] public class StudentInfo { int studentID; string lastName; string firstName; [DataMember] public int StudentID { get { return studentID; } set { studentID = value; } } [DataMember] public string FirstName { get { return firstName; } set { firstName = value; } } [DataMember] public string LastName { get { return lastName; } set { lastName = value; } } } }
在這個實體類中,DataContract代表數據契約,DataMeber代表數據成員,加上這些Attribute后,能夠傳送給Client端。
然后是一個接口,這個接口定義了服務契約和操作契約:

using System.Collections.Generic; using System.ServiceModel; namespace WCFServiceGeneratedByConfig { [ServiceContract] public interface IStudentService { [OperationContract] string GetStudentFullName(int studentId); [OperationContract] IEnumerable<StudentInfo> GetStudentInfo(int studentId); } }
然后是具體的實現方法:

using System.Collections.Generic; using System.Linq; namespace WCFServiceGeneratedByConfig { public class StudentService : IStudentService { List<StudentInfo> list = new List<StudentInfo>(); public StudentService() { list.Add(new StudentInfo { StudentID = 10010, FirstName = "Shi", LastName = "Chaoyang" }); list.Add(new StudentInfo { StudentID = 10011, FirstName = "Liu", LastName = "Jieus" }); list.Add(new StudentInfo { StudentID = 10012, FirstName = "Cheung", LastName = "Vincent" }); list.Add(new StudentInfo { StudentID = 10013, FirstName = "Yang", LastName = "KaiVen" }); } public string GetStudentFullName(int studentId) { IEnumerable<string> Student = from p in list where p.StudentID == studentId select p.FirstName + " " + p.LastName; return Student.Count() != 0 ? Student.First() : string.Empty; } public IEnumerable<StudentInfo> GetStudentInfo(int studentId) { IEnumerable<StudentInfo> Student = from p in list where p.StudentID == studentId select p; return Student; } } }
這個方法里,我們有兩個函數,一個能夠根據學生點獲取學生全名,另一個是根據學生點獲取學生的實體對象。
好了,讓我們來編譯這個項目,得到一個WCFServiceGeneratedByConfig.exe文件。
然后,我們需要配置文件來讓服務器端啟動,所以這里我們要用WCF Service Configuration Editor
工具來進行,由於在VS2008 和VS2010中帶有這個軟件,我們可以直接通過菜單->Tools->WCF Service Configuration Editor來打開。
首先,點擊File->New config, 打開Service的Configuration界面。
然后,點擊Create a new service…,在彈出的界面中,我們選擇剛才生成的那個WCFServiceGeneratedByConfig.exe文件。雙擊之后,軟件自動顯示出了里面含有的Service:
點選那個Service,然后點擊兩次next,我們會看到出現了選擇Communation Mode的界面,這里由於我們用的是net.tcp,所以我選擇了第一個:TCP。
然后點擊Next,我們會看到要我們填寫EndPoint,這里我隨便填寫了一個:
之后,點擊Next知道Finish,然后,我們的最基本的配置就結束了。
回到Config界面之后,我們點擊Advanced->Service Behaviors->New Service Behavior Configuration,在彈出的界面中,我們點擊Add->serviceMetadata:
然后點擊Add,我們就添加了一個Behavior Element。點擊剛剛生成的serviceMetadata節點,在顯示的界面中,設置HttpGetEnabled為true。
然后點擊原來的Service節點下的Host節點,在Base Address欄目下單擊Add,添加如下的Base Address:
最后點擊OK。然后點擊菜單File->Save As 保存到項目文件夾下即可。
這里是生成的代碼:

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="StudentBehavior"> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" /> </behavior> </serviceBehaviors> </behaviors> <services> <service name="WCFServiceGeneratedByConfig.StudentService"> <endpoint address="net.tcp://127.0.0.1:50001/StudentServiceEndPoint" binding="netTcpBinding" bindingConfiguration="" contract="WCFServiceGeneratedByConfig.IStudentService" /> <host> <baseAddresses> <add baseAddress="net.tcp://127.0.0.1:50001/StudentServiceEndPoint" /> </baseAddresses> </host> </service> </services> </system.serviceModel> </configuration>
這一步做完后,我們需要讓服務能夠啟動,怎么啟動呢?請看下面的代碼:

using System; using System.ServiceModel; using System.ServiceModel.Description; namespace WCFServiceGeneratedByConfig { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(StudentService))) { ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); if (smb == null) host.Description.Behaviors.Add(new ServiceMetadataBehavior()); //暴露出元數據,以便能夠讓SvcUtil.exe自動生成配置文件 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex"); //開啟服務 host.Open(); Console.WriteLine("Service listen begin to listen..."); Console.WriteLine("press any key to teriminate..."); Console.ReadKey(); host.Abort(); host.Close(); } } } }
代碼中的注釋部分非常重要,我們一定要添加,否則下面的步驟不能進行,具體的原因,參加我的另一篇文章:在net.tcp模式下,由SvcUtil.exe生成代理類文件和配置文件
然后運行這個ConsoleApplication。
接下來,找到SvcUtil.exe,C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\SvcUtil.exe,在CMD窗口下運行如下命令:
C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\SvcUtil.exe net.tcp://127.0.0.1:50001/StudentServiceEndPoint
這樣,這個小工具就會自動的給我們生成代理類和配置文件
Microsoft (R) Service Model Metadata Tool [Microsoft (R) Windows (R) Communication Foundation,版本 3.0.4506.2152] 版權所有(c) Microsoft Corporation。保留所有權利。 正在嘗試使用 WS-Metadata Exchange 從“net.tcp://127.0.0.1:50001/StudentServiceEndPoint”下載元數據。此 URL 不支持 DISCO。 正在生成文件... E:\WCF\WCF_ChatRoom\StudentService.cs E:\WCF\WCF_ChatRoom\output.config 請按任意鍵繼續. . .
客戶端的配置步驟
接下來,新建一個WindowsFormsApplication程序,將這個代理類拷入,配置文件修改名稱為App.config拷入,
然后在Form1.cs中拖入一個文本框,一個按鈕,一個DataGridView,后台代碼如下:

using System; using System.Collections.Generic; using System.Windows.Forms; using WCFServiceGeneratedByConfig; namespace WindowsFormsApplication3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Action action = new Action(Bind); action.BeginInvoke(new AsyncCallback((iar) => { Action actionEnd = (Action)iar.AsyncState; actionEnd.EndInvoke(iar); }), action); } private void Bind() { StudentServiceClient client = new StudentServiceClient(); IEnumerable<StudentInfo> x = client.GetStudentInfo(Int32.Parse(textBox1.Text)); dataGridView1.Invoke((Action)(() => { dataGridView1.DataSource = x; })); } } }
啟動這個實例,輸入學生ID,我們成功得到了服務端返回的值。
在本機和公網上的運行結果
那么能不能在公網上使用呢?呵呵,這個當然,將服務端拷貝到外網的一台機器上,然后修改服務器端的配置文件中的地址為:net.tcp://169.*.*.124:50001/ StudentServiceEndPoint,然后將本機的配置文件中的地址也修改為這個,最后運行,依然能夠得到返回的結果。
源代碼下載