客戶端發送請求,然後一直等待服務端的響應(非同步調用除外),期間處於假死狀態,直到服務端有了答覆後,客戶端才會繼續向下執行,這種方式相對單向模式來說靈活性差,但是安全性高,因為是單線程的所以安全性極高,適用於有數據返回的請求。 ...
一、概述
WCF在通信過程中有三種模式:請求與答覆、單向、雙工通信。以下我們一一介紹。
二、請求與答覆模式
客戶端發送請求,然後一直等待服務端的響應(非同步調用除外),期間處於假死狀態,直到服務端有了答覆後,客戶端才會繼續向下執行,這種方式相對單向模式來說靈活性差,但是安全性高,因為是單線程的所以安全性極高,適用於有數據返回的請求。如下圖所示(下圖來自網路,圖中的粗紅線在此時代表順序並不代表調用):
請求與答覆模式為WCF的預設模式,如下代碼所示:
/// <summary>
/// 請求與答覆模式,預設模式
/// </summary>
/// <param name="Id">書籍ID</param>
/// <returns></returns>
[OperationContract]
string GetBook(string Id);
只要是使用特性“[OperationContract]”即使返回值是void 也屬於請求與答覆模式。
缺點:如果用WCF在程式A中上傳一個2G的文件,那麼要想執行程式B也許就是幾個小時後的事情了。如果操作需要很長的時間,那麼客戶端程式的響應能力將會大大的下降。
優點:有返回值我們就可以向客戶端返回錯誤信息,如:只接收".rar"文件等信息。
實例:
//服務端介面
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfServiceLib
{
// 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的介面名“IBookService”。
[ServiceContract]
public interface IBookService
{
/// <summary>
/// 請求與答覆模式,預設模式
/// </summary>
/// <param name="Id">書籍ID</param>
/// <returns></returns>
[OperationContract]
string GetBook(string Id);
}
}
//服務端實現
public class BookService : IBookService
{
public string GetBook(string Id)
{
System.Threading.Thread.Sleep(20000);
int bookId = Convert.ToInt32(Id);
Books book = SetBook(bookId);
string xml = XMLHelper.ToXML<Books>(book);
return xml;
}
public Books SetBook(int Id)
{
Books book = new Books();
book.BookID = Id;
book.AuthorID = 1;
book.Category = "IBM";
book.Price = 39.99M;
book.Numberofcopies = 25;
book.Name = "DB2資料庫性能調整和優";
book.PublishDate = new DateTime(2015, 2, 23);
return book;
}
}
//客戶端調用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnGetBook_Click(object sender, EventArgs e)
{
textBox1.Text += string.Format("開始調用wcf服務:{0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
BookServiceReference.BookServiceClient client = new BookServiceReference.BookServiceClient();
string book = client.GetBook("5");
textBox1.Text += book;
textBox1.Text += string.Format("\r\n調用結束:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
}
在上例中,我們在服務端讓線程睡眠20秒然後再返回客戶端,那麼客戶端兩次顯示當前時間的間隔必然在20秒以上,如下圖1,2所示:
圖1
圖2
二、單向模式
單向模式顧名思義是一種單向的請求,客戶端向服務端發出消息請求後客戶端就和服務端失去了聯繫,請求的一端不會關心是否返回結果繼續往下執行。也就是說客戶端發送請求後就會向下繼續執行,不會等待服務端返回消息,而且服務端接收消息並執行服務,這種單向的模式其實是一種多線程下的操作,客戶端發出消息後, 客戶端和服務端就會同時執行,這樣它們之間就不會互相衝突,同時也是線程安全的,提高了執行效率。
單向模式只需要在方法聲明中添加IsOneWay屬性即可,它即可表示該消息的調用使用的是單向模式。如下圖所示:
單向模式要在OpertaionContract的屬性中顯示設置值,代碼如下:
[OperationContract(IsOneWay = true)]
void ShowName(string name);
優缺點與“請求響應模式”差不多倒過來。
特點:使用 IsOneWay=true 標記的操作不得聲明輸出參數、引用參數或返回值
實例:
//服務端介面
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfServiceLib
{
// 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的介面名“IBookService”。
[ServiceContract]
public interface IBookService
{
/// <summary>
/// 請求與答覆模式,預設模式
/// </summary>
/// <param name="Id">書籍ID</param>
/// <returns></returns>
[OperationContract]
string GetBook(string Id);
/// <summary>
/// 單工模式,顯示名稱
/// </summary>
/// <param name="name">書籍名稱</param>
[OperationContract(IsOneWay = true)]
void ShowName(string name);
}
}
//服務端實現
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WcfServiceLib
{
// 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼、svc 和配置文件中的類名“BookService”。
// 註意: 為了啟動 WCF 測試客戶端以測試此服務,請在解決方案資源管理器中選擇 BookService.svc 或 BookService.svc.cs,然後開始調試。
public class BookService : IBookService
{
/// <summary>
/// 請求與答覆模式,預設模式
/// </summary>
/// <param name="Id">書籍ID</param>
/// <returns></returns>
public string GetBook(string Id)
{
System.Threading.Thread.Sleep(20000);
int bookId = Convert.ToInt32(Id);
Books book = SetBook(bookId);
string xml = XMLHelper.ToXML<Books>(book);
return xml;
}
public Books SetBook(int Id)
{
Books book = new Books();
book.BookID = Id;
book.AuthorID = 1;
book.Category = "IBM";
book.Price = 39.99M;
book.Numberofcopies = 25;
book.Name = "DB2資料庫性能調整和優";
book.PublishDate = new DateTime(2015, 2, 23);
return book;
}
/// <summary>
/// 單工模式,顯示名稱
/// </summary>
/// <param name="name">名稱</param>
public void ShowName(string name)
{
Console.WriteLine(string.Format("書籍名稱:{0},日期時間{1}", name, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
}
}
}
//客戶端調用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnGetBook_Click(object sender, EventArgs e)
{
textBox1.Text += string.Format("開始調用wcf服務:{0}\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
BookServiceReference.BookServiceClient client = new BookServiceReference.BookServiceClient();
string book = client.GetBook("5");
textBox1.Text += book;
textBox1.Text += string.Format("\r\n調用結束:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
/// <summary>
/// 單工模式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonOneWay_Click(object sender, EventArgs e)
{
textBox1.Text += string.Format("開始調用wcf服務:{0}\r\n\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
BookServiceReference.BookServiceClient client = new BookServiceReference.BookServiceClient();
client.ShowName("科學可以這樣看叢書");
textBox1.Text += string.Format("\r\n\r\n調用結束:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
}
在單向模式中與請求響應模式最主要的就是加IsOneWay屬性,運行效果如下圖: