本文系統闡述 WCF 三種訊息交換模式(One-Way、Request/Reply、Duplex)的特徵、定義方式、適用場景,並提供完整程式碼範例驗證各模式行為差異。適合具備 SOA 基礎概念與分散式開發經驗的讀者。
| 模式 | 特徵 | 回傳值 | 參數限制 | 適用場景 |
|---|---|---|---|---|
| One-Way | 單向發送,有去無回(肉包子打狗) | 只能 void |
不可有 ref/out 參數 |
事件通知、日誌記錄、非關鍵狀態更新 |
| Request/Reply | 請求-回應,預設模式,類似 HTTP | 任意型別(含 void 也會產生回應訊息) |
支援 ref/out |
大多數業務操作:查詢、CRUD、運算 |
| Duplex | 雙工,雙方可互為客戶端/服務端,支援回調 | 任意型別 | 支援 ref/out |
即時通訊、進度通知、事件訂閱、長時間任務回報 |
[ServiceContract]
public interface IOneWayJob {
[OperationContract(IsOneWay = true)]
void Do(string jobName);
}
// 實作
public class OneWayJob : IOneWayJob {
public void Do(string jobName) {
Thread.Sleep(1000); // 模擬耗時
Console.WriteLine($"服務執行任務: {jobName}");
}
}

[ServiceContract]
public interface INormalJob {
[OperationContract] // 預設 IsOneWay=false
string Do(string jobName);
}
// 實作
public class NormalJob : INormalJob {
public string Do(string jobName) {
Thread.Sleep(1000);
Console.WriteLine($"服務執行任務: {jobName}");
return "成功";
}
}

// 1. 定義回調合約(客戶端需實作)
[ServiceContract]
public interface ICallback {
[OperationContract(IsOneWay = true)]
void Done(int elapsedMs);
}
// 2. 服務合約引用回調
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IJob {
[OperationContract]
string Do(string jobName);
}
// 3. 服務實作:透過 OperationContext 取得回調通道
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Job : IJob {
public string Do(string jobName) {
var callback = OperationContext.Current.GetCallbackChannel<ICallback>();
var sw = Stopwatch.StartNew();
Thread.Sleep(1000);
Console.WriteLine($"服務執行任務: {jobName}");
sw.Stop();
callback.Done((int)sw.ElapsedMilliseconds); // 發起回調
return "成功";
}
}


Duplex 需支援雙工訊息交換模式的繫結:
WSDualHttpBinding(HTTP 雙工,需客戶端開啟監聽埠)NetTcpBinding(TCP 雙工,效能最佳,推薦內網)NetNamedPipeBinding(同機器進程間雙工)⚠️ BasicHttpBinding、WSHttpBinding 不支援 Duplex。
使用 WSDualHttpBinding 時,客戶端必須指定 clientBaseAddress(預設嘗試佔用 80 埠常失敗):
<endpoint ... binding="wsDualHttpBinding">
<identity><dns value="localhost" /></identity>
</endpoint>
<client>
<endpoint ...>
<callbackEndpoint address="https://localhost:8080/ClientCallback" /> <!-- 指定回調位址 -->
</endpoint>
</client>
| 專案 | 類型 | 核心檔案 |
|---|---|---|
| Jillzhang.Messaging.Contract | Class Library | IOneWayJob.cs, INormalJob.cs, IJob.cs, ICallback.cs |
| Jillzhang.Messaging.Service | Class Library | OneWayJob.cs, NormalJob.cs, Job.cs |
| Jillzhang.Messaging.Host | Console App | Program.cs, App.config |
| Jillzhang.Messaging.WebSite | Web Site | *.svc, web.config |
| Jillzhang.Messaging.Client | Console App | OnewayProxy.cs, NormalJobProxy.cs, DuplexProxy.cs, MyCallback.cs, Program.cs, app.config |


<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpBinding" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:6987/Service/duplex"
binding="netTcpBinding" bindingConfiguration="netTcpBinding"
contract="Jillzhang.Messaging.Contract.IJob" name="NetTcpBinding">
<identity><dns value="localhost" /></identity>
</endpoint>
<!-- one-way、normal 端點類似 -->
</client>
</system.serviceModel>
// MyCallback.cs - 客戶端實作回調
public class MyCallback : ICallback {
public void Done(int elapsedMs) {
Console.WriteLine($"[回調] 任務完成,耗時 {elapsedMs} ms");
}
}
// Program.cs - 呼叫三種模式
static void DuplexCall() {
var callback = new MyCallback();
var ctx = new InstanceContext(callback);
var proxy = new JobClient(ctx);
string result = proxy.Do("duplex job");
Console.WriteLine($"收到回覆: {result}");
}
static void OneWayCall() {
var proxy = new OneWayJobClient();
proxy.Do("one-way job"); // 立即返回,不等待
Console.WriteLine("請求已送出");
}
static void NormalCall() {
var proxy = new NormalJobClient();
string result = proxy.Do("request/reply job"); // 阻塞等待回應
Console.WriteLine($"收到回覆: {result}");
}

可見三種模式依序執行,Duplex 模式額外觸發回調。

One-Way:立即印出「請求完成」
Request/Reply:阻塞 1 秒後印出回覆
Duplex:阻塞 1 秒收到回覆,隨後回調印出耗時資訊
| 維度 | One-Way | Request/Reply | Duplex |
|---|---|---|---|
| 方向 | 單向 | 雙向(請求-回應) | 雙向(對等) |
| 阻塞性 | 非阻塞 | 阻塞 | 阻塞(等待回覆)+ 非阻塞回調 |
| 錯誤傳遞 | 無法傳遞 | SOAP Fault 返回 | SOAP Fault + 回調異常 |
| 繫結支援 | 所有 | 所有 | NetTcp, WSDualHttp, NetNamedPipe |
| 會話需求 | 無 | 無 | 需 Session |
| 典型用途 | 通知、日誌、火後不理 | 標準 RPC | 即時推送、長任務進度、聊天 |