tcp 下的双向通讯:
由于使用tcp的方式,会遵循tcp 的方式,即和HOstServer端先创建一个连接,然后,所有的命令都会在这个connection上进行传输,当然如果是CallBack的部分的数据也会在同一个Connection中进行传输。下面就看下如何创建一个简单的Duplex 。
以下修改 学习笔记中(1)中的程序来实现。 工程架构如下:
1.修改MyData命名空间的类。如下:
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.ServiceModel;
5
6
7namespace TESTWCF.MyData
8{
9 [ServiceContract(Namespace = "http://www.cnblogs.net/zhucl1006", CallbackContract = typeof(ICallBack))]
10 public interface IMyDataService
11 {
12 [OperationContract(IsOneWay = true)]
13 void GetServerTime(string userName);
14 }
15
16
17 [ServiceContract(Namespace = "http://www.cnblogs.net/zhucl1006")]
18 public interface ICallBack
19 {
20 [OperationContract(IsOneWay=true)]
21 void ServerReturn(string times);
22 }
23
24}
2using System.Collections.Generic;
3using System.Text;
4using System.ServiceModel;
5
6
7namespace TESTWCF.MyData
8{
9 [ServiceContract(Namespace = "http://www.cnblogs.net/zhucl1006", CallbackContract = typeof(ICallBack))]
10 public interface IMyDataService
11 {
12 [OperationContract(IsOneWay = true)]
13 void GetServerTime(string userName);
14 }
15
16
17 [ServiceContract(Namespace = "http://www.cnblogs.net/zhucl1006")]
18 public interface ICallBack
19 {
20 [OperationContract(IsOneWay=true)]
21 void ServerReturn(string times);
22 }
23
24}
注意方法中使用的OperationContract中要使用IsOneWay=true , 否则在调用的时候, 返回callback 后Client端会被锁住。
至于OperationContract中的属性,我也了解很少,以后再补上详细的描述。
isOneWay=true 理解为:则表明客户端与服务端之间只有请求,没有响应。
HostServer端调整:
添加一个MyDataService的类,继承IMyDataService。如下:
using System;
using System.Collections.Generic;
using System.Text;
using TESTWCF.MyData;
using System.ServiceModel;
namespace TESTWCF.HostServer
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyDataService : IMyDataService
{
#region IMyDataService 成员
public void GetServerTime(string userName)
{
string str = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
ICallBack callback = OperationContext.Current.GetCallbackChannel<ICallBack>();
callback.ServerReturn(str);
}
#endregion
}
}
在这里可以看到,在GetServerTime的方法中,使用OperationContext.Current.GetCallBAckChannel的方法获取当前连接的CallBack Contact。
然后调用该契约的方法,调用Client端的方法。
Clinet端修改:
app.config :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8010/MyData" binding="netTcpBinding" bindingConfiguration=""
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint" />
<!--<endpoint address="http://localhost:8090/MyData" binding="basicHttpBinding"
contract="TESTWCF.MyData.IMyDataService" />-->
</client>
</system.serviceModel>
</configuration>
窗体代码:<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8010/MyData" binding="netTcpBinding" bindingConfiguration=""
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint" />
<!--<endpoint address="http://localhost:8090/MyData" binding="basicHttpBinding"
contract="TESTWCF.MyData.IMyDataService" />-->
</client>
</system.serviceModel>
</configuration>
Code
运行后即可实现 在ServerReturn中得到返回值,并显示到窗体上。Http 下的双向通讯:
在Http的协议下,由于http协议是 一个应用层的协议,它采用传统的Request/Reply的方式进行通信,所以,当要实现双向通讯的时候,需要在Client端也建立一个Server端,用来接收CallBack的数据。
在上面的例子中,可以通过修改app.config来实现http下的双向。
Server端的app.config 修改如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="TESTWCF.HostServer.MyDataService" behaviorConfiguration="serviceBehavior">
<endpoint binding="wsDualHttpBinding" contract="TESTWCF.MyData.IMyDataService" address="MyData" />
<endpoint binding="netTcpBinding" contract="TESTWCF.MyData.IMyDataService" address="MyData" />
<!--<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />-->
<host>
<baseAddresses>
<add baseAddress="http://localhost:8090"/>
<add baseAddress="net.tcp://localhost:8010"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Client端appconfig修改如下:<configuration>
<system.serviceModel>
<services>
<service name="TESTWCF.HostServer.MyDataService" behaviorConfiguration="serviceBehavior">
<endpoint binding="wsDualHttpBinding" contract="TESTWCF.MyData.IMyDataService" address="MyData" />
<endpoint binding="netTcpBinding" contract="TESTWCF.MyData.IMyDataService" address="MyData" />
<!--<endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" />-->
<host>
<baseAddresses>
<add baseAddress="http://localhost:8090"/>
<add baseAddress="net.tcp://localhost:8010"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="wsDualBinding_IMyData" clientBaseAddress="http://localhost:8888/myClient/" />
</wsDualHttpBinding>
</bindings>
<client>
<!--<endpoint address="net.tcp://localhost:8010/MyData" binding="netTcpBinding" bindingConfiguration=""
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint" />-->
<endpoint address="http://localhost:8090/MyData" binding="wsDualHttpBinding" bindingConfiguration="wsDualBinding_IMyData"
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint"/>
</client>
</system.serviceModel>
</configuration>
<configuration>
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="wsDualBinding_IMyData" clientBaseAddress="http://localhost:8888/myClient/" />
</wsDualHttpBinding>
</bindings>
<client>
<!--<endpoint address="net.tcp://localhost:8010/MyData" binding="netTcpBinding" bindingConfiguration=""
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint" />-->
<endpoint address="http://localhost:8090/MyData" binding="wsDualHttpBinding" bindingConfiguration="wsDualBinding_IMyData"
contract="TESTWCF.MyData.IMyDataService" name="tcpendpoint"/>
</client>
</system.serviceModel>
</configuration>
通过以上修改app.config , 就可以实现一个基于http模式下的wcf 的程序了。
个人觉得是用tcp的方式要比http的方式要好,因为tcp的方式,使用二进制的方式进行网络传输, 而http的方式使用文本的方式进行传输。tcp使用tcp的方式建立连接,保证数据不丢,而且tcp的方式是先建立一个连接,然后再该连接上进行操作 , 所以效能上也比http的方式要快。
源码下载