Wiki


Wiki Table of Contents

Page Details

Published by:
This page has not yet been rated

Silverlight Tip of the Day #12 - Full Implementation of a Silverlight Policy Server.

Filed under: [Edit Tags]

Trước khi một ứng dụng Silverlight có thể kết nối đến một server, đầu tiên nó phải kết nối thành công đến một policy server trên máy để tiếp tục kết nối.

Trong tip này tôi sẽ nói tất cả các bước bạn cần làm để tạo và chạy một policy server của riêng bạn.

Để bắt đầu, hãy tạo mới một  ứng dụng C# console. Sau đó, tạo một file mới XML được đặt tên là “clientaccesspolicy.xml” và thêm nó vào project của bạn. Đây sẽ là file mà Policy Server của bạn gửi đến client để cho phép nó tiếp tục kết nối.

Nội dung của file  “clientaccesspolicy.xml” giống như sau:

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

Chú ý rằng với Silverlight, sockets được giới hạn đến ports #4502-4534. Dầu vậy, policy server khi  gửi policy file đến connecting client sẽ chạy tại port 943.

Code dành cho policy server như sau:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
 
namespace PolicyServer
{
    // Encapsulate and manage state for a single connection from a client
    class PolicyConnection
    {
        private Socket _connection;
        private byte[] _buffer; // buffer to receive the request from the client       
        private int _received;
        private byte[] _policy; // the policy to return to the client
 
        // the request that we're expecting from the client
        private static string _policyRequestString = "<policy-file-request/>";
 
        public PolicyConnection(Socket client, byte[] policy)
        {
            _connection = client;
            _policy = policy;
 
            _buffer = new byte[_policyRequestString.Length];
            _received = 0;
 
            try
            {
                // receive the request from the client
                _connection.BeginReceive(_buffer, 0, _policyRequestString.Length, SocketFlags.None,
                    new AsyncCallback(OnReceive), null);
            }
            catch (SocketException)
            {
                _connection.Close();
            }
        }
 
        // Called when we receive data from the client
        private void OnReceive(IAsyncResult res)
        {
            try
            {
                _received += _connection.EndReceive(res);
 
                // if we haven't gotten enough for a full request yet, receive again
                if (_received < _policyRequestString.Length)
                {
                    _connection.BeginReceive(_buffer, _received, _policyRequestString.Length - _received,
                        SocketFlags.None, new AsyncCallback(OnReceive), null);
                    return;
                }
 
                // make sure the request is valid
                string request = System.Text.Encoding.UTF8.GetString(_buffer, 0, _received);
                if (StringComparer.InvariantCultureIgnoreCase.Compare(request, _policyRequestString) != 0)
                {
                    _connection.Close();
                    return;
                }
 
                // send the policy
                Console.Write("Sending policy...\n");
                _connection.BeginSend(_policy, 0, _policy.Length, SocketFlags.None,
                    new AsyncCallback(OnSend), null);
            }
            catch (SocketException)
            {
                _connection.Close();
            }
        }
 
        // called after sending the policy to the client; close the connection.
        public void OnSend(IAsyncResult res)
        {
            try
            {
                _connection.EndSend(res);
            }
            finally
            {
                _connection.Close();
            }
        }
    }
 
    // Listens for connections on port 943 and dispatches requests to a PolicyConnection
    class PolicyServer
    {
        private Socket _listener;
        private byte[] _policy;
 
        // pass in the path of an XML file containing the socket policy
        public PolicyServer(string policyFile)
        {
 
            // Load the policy file
            FileStream policyStream = new FileStream(policyFile, FileMode.Open);
 
            _policy = new byte[policyStream.Length];
            policyStream.Read(_policy, 0, _policy.Length);
            policyStream.Close();
 
 
            // Create the Listening Socket
            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
                ProtocolType.Tcp);
 
            _listener.SetSocketOption(SocketOptionLevel.Tcp, (SocketOptionName)
                SocketOptionName.NoDelay, 0);
 
            _listener.Bind(new IPEndPoint(IPAddress.Any, 943));
            _listener.Listen(10);
 
            _listener.BeginAccept(new AsyncCallback(OnConnection), null);
        }
 
        // Called when we receive a connection from a client
        public void OnConnection(IAsyncResult res)
        {
            Socket client = null;
 
            try
            {
                client = _listener.EndAccept(res);
            }
            catch (SocketException)
            {
                return;
            }
 
            // handle this policy request with a PolicyConnection
            PolicyConnection pc = new PolicyConnection(client, _policy);
 
            // look for more connections
            _listener.BeginAccept(new AsyncCallback(OnConnection), null);
        }
 
        public void Close()
        {
            _listener.Close();
        }
    }
 
    public class Program
    {
        static void Main()
        {
            Console.Write("Starting...\n");
            PolicyServer ps =
                new PolicyServer(@"<path to your file>\clientaccesspolicy.xml");
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
        }
    }
}

 

Bạn cần phải thay đổi nơi đặt file XML trên tại chỗ này  "<path to your file>\clientaccesspolicy.xml" để chương trình biết được nơi đặt đường dẫn thực trong project của bạnvà nơi bạn lưu file trên server.

Thank you,
--Mike Snow

 

 

 

 

Recent Comments

Leave the first comment for this page.