这两天研究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
没有整理过代码,大家将就着看吧!