Silverlight Working with Sockets

Silverlight和服务端进行通信前会向服务端请求一个安全策略文件,在Silverlight 3.0中这个请求端口为943、Silverlight 4.0也可以是80。请求的模式取决于你的应用程序中SocketAsyncEventArgs.SocketClientAccessPolicyProtocol所指的值为Http或Tcp。如果是Http,需要在IIS中为80的站点添加net.tcp类型的绑定,并指明端口(4502 - 4530)。Tcp则需要一个应用程序负责监听943端口,当请求为时返回你的策略文件内容。策略文件的格式可以如下:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="*">
        <domain uri="*" />
      </allow-from>
      <grant-to>
    <socket-resource port="4530" protocol="tcp" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

详细的内容可以参考Network Security Access Restrictions in Silverlight这篇文章:

http://msdn.microsoft.com/en-us/library/cc645032(v=VS.95).aspx

如果你编写的服务端需要和Silverlight进行Tcp通信,请准备一个策略服务端监听943端口。当Silverlight应用创建和服务端连接时,它会先请求你的PolicyServer并获取允许使用的端口。

关于WCF NET.TCP请参考WCF NET.TCP Protocol in Silverlight这篇文章:

http://www.silverlightshow.net/items/WCF-NET.TCP-Protocol-in-Silverlight-4.aspx

  1 using System;
  2 using System.IO;
  3 using System.Net;
  4 using System.Net.Sockets;
  5 using System.Text;
  6 using System.Threading;
  7 
  8 namespace SLPolicyServer
  9 {
 10     class Program
 11     {
 12         /// <summary>
 13         /// 主程序入口
 14         /// </summary>
 15         /// <param name="args">参数</param>
 16         static void Main(String[] args)
 17         {
 18             String policyFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "clientaccesspolicy.xml");
 19 
 20             if (args.Length == 1)
 21             {
 22                 policyFile = args[0];
 23 
 24                 Console.WriteLine(args[0]);
 25             }
 26 
 27             new Thread(() =>
 28             {
 29                 new PolicyServer(policyFile);
 30                 Thread.Sleep(Timeout.Infinite);
 31             }).Start();
 32 
 33             Console.ReadKey();
 34         }
 35     }
 36 
 37     /// <summary>
 38     /// 策略连接
 39     /// </summary>
 40     class PolicyConnection
 41     {
 42         /// <summary>
 43         /// 策略请求字符串
 44         /// </summary>
 45         private static readonly String PolicyRequestString = "<policy-file-request/>";
 46 
 47         private Socket m_connection;
 48         private Byte[] m_buffer;
 49         private Byte[] m_policy;
 50         private Int32 m_received;
 51 
 52         /// <summary>
 53         /// 构造函数
 54         /// </summary>
 55         /// <param name="client">客户端套接字</param>
 56         /// <param name="policy">策略数据</param>
 57         public PolicyConnection(Socket client, Byte[] policy)
 58         {
 59             m_connection = client;
 60             m_policy = policy;
 61             m_buffer = new Byte[PolicyRequestString.Length];
 62             m_received = 0;
 63 
 64             try
 65             {
 66                 m_connection.BeginReceive(m_buffer, 0, PolicyRequestString.Length, SocketFlags.None, new AsyncCallback(OnReceive), null);
 67             }
 68             catch (SocketException)
 69             {
 70                 m_connection.Close();
 71             }
 72         }
 73 
 74         /// <summary>
 75         /// 接收数据
 76         /// </summary>
 77         /// <param name="ar">异步结果</param>
 78         private void OnReceive(IAsyncResult ar)
 79         {
 80             try
 81             {
 82                 m_received += m_connection.EndReceive(ar);
 83 
 84                 // 发送字符不足则继续接收
 85                 if (m_received < PolicyRequestString.Length)
 86                 {
 87                     m_connection.BeginReceive(m_buffer, m_received, PolicyRequestString.Length - m_received, SocketFlags.None, new AsyncCallback(OnReceive), null);
 88 
 89                     return;
 90                 }
 91 
 92                 String request = Encoding.UTF8.GetString(m_buffer, 0, m_received);
 93 
 94                 if (StringComparer.InvariantCultureIgnoreCase.Compare(request, PolicyRequestString) != 0)
 95                 {
 96                     m_connection.Close();
 97 
 98                     return;
 99                 }
100 
101                 // 发送策略文件
102                 m_connection.BeginSend(m_policy, 0, m_policy.Length, SocketFlags.None, new AsyncCallback(OnSend), null);
103             }
104             catch (SocketException)
105             {
106                 m_connection.Close();
107             }
108         }
109 
110         /// <summary>
111         /// 发送数据
112         /// </summary>
113         /// <param name="ar">异步结果</param>
114         private void OnSend(IAsyncResult ar)
115         {
116             try
117             {
118                 m_connection.EndSend(ar);
119             }
120             finally
121             {
122                 m_connection.Close();
123             }
124         }
125     }
126 
127     /// <summary>
128     /// 策略服务
129     /// </summary>
130     class PolicyServer
131     {
132         private Socket m_listener;
133         private Byte[] m_policy;
134 
135         /// <summary>
136         /// 构造函数
137         /// </summary>
138         /// <param name="policyFile">策略文件</param>
139         public PolicyServer(String policyFile)
140         {
141             // 读取策略文件
142             FileStream policyStream = new FileStream(policyFile, FileMode.Open);
143             m_policy = new byte[policyStream.Length];
144 
145             policyStream.Read(m_policy, 0, m_policy.Length);
146             policyStream.Close();
147 
148             // 监听943端口
149             m_listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
150             m_listener.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
151             m_listener.Bind(new IPEndPoint(IPAddress.IPv6Any, 943));
152             m_listener.Listen(10);
153             m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
154         }
155 
156         /// <summary>
157         /// 关闭
158         /// </summary>
159         public void Close()
160         {
161             m_listener.Close();
162         }
163 
164         /// <summary>
165         /// 连接
166         /// </summary>
167         /// <param name="ar">异步结果</param>
168         private void OnConnection(IAsyncResult ar)
169         {
170             Socket client = null;
171 
172             try
173             {
174                 client = m_listener.EndAccept(ar);
175             }
176             catch (SocketException)
177             {
178                 return;
179             }
180 
181             // 建立策略连接
182             PolicyConnection pc = new PolicyConnection(client, m_policy);
183 
184             m_listener.BeginAccept(new AsyncCallback(OnConnection), null);
185         }
186     }
187 }
posted @ 2012-08-11 12:00  junchu25  阅读(444)  评论(0编辑  收藏  举报