Silverlight4中用net.tcp双工方式进行通信
这两天研究net.tcp与Silverlight4进行通信都快疯了,不过还好,苍天不负苦心人啊,这俩天总算是调通了。
先简单说一下,为了更好地实现双向通信,.NET Framework在 3.0的时候引入了一个全新的通信协议Net.TCP并作为WCF的一部分。现在Net.TCP将包含在Silverlight 4中,相比于HTTP Polling Duplex,它极大地改进了吞吐量和连接的数量。
我们可以通过Silverlight 4绑定到HTTP Duplex Services上,因而应用可以不断轮询服务以进行更新,这模拟了双向通讯的工作方式。Silverlight 4则引入了一个更好的解决方案:Net.TCP Port Sharing Service。与HTTP不同,Net.TCP提供了本地的双向通信机制,极大地改进了应用的性能。打开的端口可以由多个应用共享,然而Silverlight只能访问介于4502-4534范围之间的端口。
根据微软WCF开发经理Tomasz Janczuk所述,相对于HTTP Duplex来说,Net.TCP在如下方面进行了重大的改进:
* 吞吐量:对于UI线程来说提升了5.5倍,对于worker线程来说提升了870倍。
* 最大的客户端数量:服务器可支持的连接客户端数量是之前的5-6倍。
该协议适用于对通信速度要求很高的Silverlight应用。但其一个严重缺陷是所使用的一系列端口通常会被防火墙阻止,因此它不适合于公网、外部应用,而适合于局域网。另一个问题是它不支持SSL,这样就会遇到安全问题,Janczuk说将在未来解决该问题。
特分享一下这个demo,希望对大家有帮助。
项目结构如下图所示: WebChat.Service 是一个宿主程序,主要是用来向Silverlight提供服务和监听943与4502-4534这个范围的自定端口的。
我们启动WebChat.Service宿主程序,进行监听商品,在命令提示符下打入netstat -na来查看我们监听的端口。
我监听的是943和4503这两个端口。
Silverlight使用net.tcp访问的时候要求请一个有策略文件,可以在程序里面这写也可以放到项目的根目录下。clientaccesspolicy.xml这个是必须的
如果您使用的是vs2010的话,可以在“在线模版”里面找到Silverlight TCP Socket Policy这个模版,新建就可以得到监听943端口的程序。哈哈!
里面有两个cs文件,
SocketPolicy.cs
1 public static class SocketPolicy
2 {
3 public const string Policy = @"
4 <?xml version=""1.0"" encoding =""utf-8""?>
5 <access-policy>
6 <cross-domain-access>
7 <policy>
8 <allow-from>
9 <domain uri=""*"" />
10 </allow-from>
11 <grant-to>
12 <socket-resource port=""4502-4530"" protocol=""tcp"" />
13 </grant-to>
14 </policy>
15 </cross-domain-access>
16 </access-policy>
17 ";
18 }
还有一个文件,内容太长,这里就不给代码了,大家可以自己新建一下看看。
拷到你的项目中就可以,不用手写。
由于代码很多这里我就不全写出来了,只把需要注意的地方告诉大家,我会把整个的demo提供给大家下载。
App.config 做为这个宿主程序的灵魂,这个破config整得我都快疯掉了。这里面就是普通的wcf配置,请注意一下我写注释的地方就可以。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <system.web>
4 <compilation debug="true" />
5 </system.web>
6 <system.serviceModel>
7 <protocolMapping>
8 <add scheme="tcp" binding="netTcpBinding"/>
9 </protocolMapping>
10
11 <bindings>
12 <customBinding> <!--注意,这里只能使用自定义的绑定,应为Silverlight4测试版并不完全技术net.tcp-->
13 <binding name="WebChat.Service.ChatService1">
14 <binaryMessageEncoding></binaryMessageEncoding>
15 <tcpTransport></tcpTransport>
16 </binding>
17 </customBinding>
18 <netTcpBinding>
19 <binding name ="myTcpBinding" portSharingEnabled="true"></binding>
20 </netTcpBinding>
21 </bindings>
22
23 <services>
24 <service behaviorConfiguration="WebChat.Service.ChatServiceBehavior" name="WebChat.Service.ChatService">
25 <endpoint
26 address="Service" binding="customBinding"
27 contract="WebChat.Service.IChatService"
28 bindingConfiguration="WebChat.Service.ChatService1" >
29 </endpoint>
30 <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> <!--这个一个要写的!!!暴露元数据。-->
31 <host>
32 <baseAddresses>
33 <add baseAddress="http://localhost:4504/"/>
34 <add baseAddress="net.tcp://localhost:4503/"/>
35 </baseAddresses>
36 </host>
37 </service>
38 </services>
39 <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
40 <behaviors>
41 <serviceBehaviors>
42 <behavior name="WebChat.Service.ChatServiceBehavior">
43 <serviceMetadata httpGetEnabled="true" />
44 <serviceDebug includeExceptionDetailInFaults="false" />
45 </behavior>
46 </serviceBehaviors>
47 </behaviors>
48 </system.serviceModel>
49 </configuration>
宿主程序启动
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 PolicyServer ps = new PolicyServer(SocketPolicy.Policy); //启动943策略文件监听端口
6
7 ServiceHost host = new ServiceHost(typeof(WebChat.Service.ChatService));
8 Console.WriteLine();
9 host.Open();
10 System.Console.WriteLine("聊天室服务器开始监听...");
11 System.Console.WriteLine("按 ENTER 停止服务器监听...");
12 System.Console.ReadLine();
13 host.Abort();
14 host.Close();
15 ps.Close();
16 }
17 }
客户端添加服务的时候没有什么太需要注意的地方。写入你本机的ip或127.0.0.1或localhost加上你监听的端口号再加上mex(请求元数据)就OK了。
在添加引用和调用的时候宿主程序一定要运行,应为SL访问的时候是通过你监听的端口进数据通信的。
1 private void btnClick_Click(object sender, RoutedEventArgs e)
2 {
3
4 ServiceReference1.ChatServiceClient sc;
5 EndpointAddress ea = new EndpointAddress("net.tcp://localhost:4503/Service");
6 BindingElement metaElement = new TcpTransportBindingElement();
7 CustomBinding metaBind = new CustomBinding(metaElement);
8
9
10 sc = new ServiceReference1.ChatServiceClient(metaBind, ea);
11 sc.JoinAsync("测试用户名");
12 sc.JoinCompleted += (se, args) =>
13 {
14 MessageBox.Show(args.Result[0]);
15 };
16 }
EndpointAddress ea = new EndpointAddress("net.tcp://localhost:4503/Service");
需要注意的是net.tcp://localhost:4503/Service这个终结点的地址是你ip+监听的端口+宿主程序app.config中定义的终结点地址
<endpoint
address="Service" binding="customBinding"
contract="WebChat.Service.IChatService"
bindingConfiguration="WebChat.Service.ChatService1" >
</endpoint>
下载地址:http://download.csdn.net/source/1910480
没有整理过代码,大家将就着看吧!