WCF雙工通訊
在WCF通訊中,如果實現要得到服務端處理的結果,一種方式是在契約中指定呼叫方法帶返回值(IsOneWay=false),但這種方式是有缺陷的,如果服務端處理時間過長,則客戶端也需要長時間等待。
另一種方式是通過雙工通訊,使用回撥來實現。但回撥的時候,回撥方法中不應該有耗時操作,否則當服務端處理完成退出的時間,回撥訊息會丟失。
目前WCF支援雙工的繫結方式有:WSDualHttpBinding,NetTcpBinding與NetNamedPipeBinding三種,其它繫結方式不支援雙工。
下面以一個簡短的例子說明雙工通訊。
1、定義契約
[ServiceContract(Namespace = "http://cnblog.com/zhili/", CallbackContract = typeof(ICallback))]
public interface ICalculator
{
[OperationContract(IsOneWay = true)]
void Multiple(double a, double b);
[OperationContract(IsOneWay = true)]
void DisplayString(string name);
}
其中指定了回撥契約是ICallback。
// 回撥契約的定義,此時回撥契約不需要應用ServiceContractAttribute特性
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void DisplayResult(double x, double y, double result);
[OperationContract(IsOneWay = false, ProtectionLevel = ProtectionLevel.EncryptAndSign)]
string DisplayStringResult(string retStr);
}
我們看到,回撥第二個方法有返回值。這個在服務行為配置中要有特殊配置,否則會卡死。
2、服務端實現
實現服務契約:
// 服務契約的實現
[ServiceBehavior(IncludeExceptionDetailInFaults = true,ConcurrencyMode = ConcurrencyMode.Multiple)]
public class CalculatorService : ICalculator
{
#region ICalculator Members
public void Multiple(double a, double b)
{
for (int i = 1; i < 100; i++)
{
double result = a * b;
// 通過客戶端例項通道
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
// 對客戶端操作進行回撥
callback.DisplayResult(a, b, result);
Console.WriteLine("Callback Times {0} at time {1}", i, DateTime.Now.ToString("hh:mm:ss tt zz"));
}
Program.ExitFlag = true;
}
public void DisplayString(string name)
{
for (int i = 1; i < 100; i++)
{
// 通過客戶端例項通道
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
// 對客戶端操作進行回撥
string retStr = callback.DisplayStringResult("Hello " + name);
Console.WriteLine("Callback Times {0} at time {1}, ret={2}", i, DateTime.Now.ToString("hh:mm:ss tt zz"), retStr);
}
Program.ExitFlag = true;
}
#endregion
}
其中ServiceBehavior屬性的ConcurrencyMode = ConcurrencyMode.Multiple配置就是配置回撥方法帶返回值問題(IsOneWay=false),如果不設定這個屬性,或者設定為Single,上述回撥方法呼叫時會卡死。
主程式如下:
class Program
{
public static bool ExitFlag = false;
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
host.Opened += delegate
{
Console.WriteLine("Service start now....");
};
host.Open();
while (!ExitFlag)
{
Thread.Sleep(500);
}
}
}
}
主程式配置(App.Config):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8080/Metadata"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="NMS.WCFDemo.Server.CalculatorService">
<endpoint address="net.tcp://localhost:9003/CalculatorService" binding="netTcpBinding" contract="NMS.WCFDemo.Contract.ICalculator"/>
</service>
</services>
</system.serviceModel>
</configuration>
3、客戶端
建立完客戶端程式後,新增一個服務引用,指向上面配置檔案的地址http://localhost:8080/Metadata獲取服務引用。(新增服務引用時服務程式必須已經在執行)
實現回撥契約:
// 客戶端中對回撥契約的實現
public class CallbackWCFService : ICalculatorCallback
{
private int i = 1;
public void DisplayResult(double a, double b, double result)
{
Console.WriteLine("{4} : {0} * {1} = {2} ====== AT Time {3}", a, b, result, DateTime.Now.ToString("hh:mm:ss tt zz"), i++);
Thread.Sleep(1000);
}
public string DisplayStringResult(string retStr)
{
Console.WriteLine("{0} : recevie msg {1} ====== AT Time {2}", i++, retStr, DateTime.Now.ToString("hh:mm:ss tt zz"));
Thread.Sleep(1000);
return i.ToString();
}
}
客戶端主程式:
// 客戶端實現,測試回撥操作
class Program
{
static void Main(string[] args)
{
InstanceContext instanceContex = new InstanceContext(new CallbackWCFService());
CalculatorClient proxy = new CalculatorClient(instanceContex);
if (args[0] == "1")
{
proxy.Multiple(2, 3);
}
else
{
Console.WriteLine("Call string ...");
proxy.DisplayString("Client");
}
Console.Read();
}
}
客戶端配置檔案(App.Config)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_ICalculator" />
<binding name="NetTcpBinding_ICalculator1" />
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:9003/CalculatorService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICalculator"
contract="NMS.WCFDemo.Contract.ICalculator" name="NetTcpBinding_ICalculator" />
<endpoint address="net.tcp://localhost:9003/CalculatorService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ICalculator1"
contract="ServiceReference1.ICalculator" name="NetTcpBinding_ICalculator1">
<identity>
<userPrincipalName value="DESKTOP-4D9M16Hwangcc" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
然後執行程式就能看到效果了。
相關文章
- 單工,半雙工,全雙工通訊區別
- 全雙工通訊的 WebSocketWeb
- UDP雙向通訊UDP
- 雙向通訊之websocketWeb
- 雙向通訊之SSE
- 工業通訊協議(一)- CAN協議
- 工信部:2018年第2季度通訊業主要通訊能力
- 工信部:2021年一季度通訊業主要通訊能力
- 物聯網智慧家居中使用WebSocket和Spring Boot實現全雙工客服通訊 -DZone JavaWebSpring BootJava
- 工信部:2021年1-9月份通訊業主要通訊能力
- WCF系列教程地址
- 樂訊通雲通訊:物聯網路卡在工業領域有哪些應用
- 工信部:2020年第四季度通訊業主要通訊能力
- MEF:2021年員工移動通訊報告
- 全雙工與半雙工技術解析
- C# WCF入門C#
- 工信部:2019年通訊業統計公報
- 工信部:2021年通訊業統計公報
- 工信部:2022年通訊業統計公報
- uni-app上下級頁面資料雙向通訊APP
- Java與WCF互動(一):Java客戶端呼叫WCF服務 (轉)Java客戶端
- WCF服務端的.NET Core支援專案Core WCF 正式啟動服務端
- [WCF許可權控制]利用WCF自定義授權模式提供當前Principal模式
- Channel: flutter平臺層與執行層的雙向通訊Flutter
- 艾偉:WCF安全之EndPointIdentityIDE
- IIS部署WCF詳細教程
- 程序間的通訊(訊號通訊)
- 【WebRTC 跨端通訊】React + React Native 雙端影片聊天、螢幕共享Web跨端React Native
- 現場匯流排與工業乙太網通訊模型模型
- 工信部:2020年通訊業統計資料公報
- 乾元通工業級4G/5G多卡聚合路由器(應急通訊、車載通訊、影片傳輸)路由器
- 學習WCF之路,長期更新
- 【React】元件通訊 - 跨層通訊React元件
- vue 自定義元件 v-model雙向繫結、 父子元件同步通訊Vue元件
- 工信部:2018年第2季度通訊水平分省情況
- 如何打通 SAP Cloud for Customer 系統和微信公眾號的雙向訊息通訊功能Cloud
- 高精度原子鐘,雙向通訊,俄將接入我國北斗衛星系統
- 全雙工與半雙工技術解析及其應用場景