[C#][Silverlight] Socket 連線–Error Code 10013 嘗試存取通訊端被拒絕,因為存取權限不足。 解決方案

  • 15878
  • 0
  • 2011-06-11

在Silverlight底下利用Socket連線時必須由目標主機為Socket提供一份ClientAccessPolicy文件,來敘述這台電腦的客端存取政策,如果Socket無法成功從目標主機下載到這份文件,就會發生這個「AccessDenied(ErrorCode: 10013):嘗試存取通訊端被拒絕,因為存取權限不足。」這樣子的錯誤。

在Silverlight底下利用Socket連線時必須由目標主機為Socket提供一份ClientAccessPolicy文件,來敘述這台電腦的客端存取政策,如果Socket無法成功從目標主機下載到這份文件,就會發生這個「AccessDenied(ErrorCode: 10013):嘗試存取通訊端被拒絕,因為存取權限不足。」這樣子的錯誤。

 

Silverlight提供兩種方式來下載這份文件:

hostname = 目標主機。

HTTP通訊協定方式:由http://hostname:80/ClientAccessPolicy.xml 這個路徑來下載,由於通訊埠號是無法切換的,並且佔用了http通訊協定的預設埠80,因此我並沒有使用這種方式。

TCP通訊協定方式:以UTF-8編碼方式向目標主機943號端點傳送

的要求字串,並且將回傳的位元組以UTF-8來轉回字串解讀。由於943號端點平常好像很少會用到,所以我選擇這個方式,也因此必須實作一個簡單的伺服器。

 

[完整範例程式碼下載:ClientAsscessPolicyServerDemo.zip]

 

※全文歡迎轉載但請註明出處,謝謝。※

using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace ClientAsscessPolicyServerDemo
{
    /// <summary>
    /// 用於提供Silverlight下的Socket客端存取政策。
    /// </summary>
    public class ClientAccessPolicyServer
    {
        private const String REQUEST_STR = "<policy-file-request/>";
        private String _PolicyContext = "";
        /// <summary>
        /// 取得或設定客端存取政策的內容。
        /// </summary>
        public String PolicyContext
        {
            get { return _PolicyContext; }
            set
            {
                if (_PolicyContext != value)
                {
                    this._PolicyContext = value;
                    this.PolicyContextBuffer = Encoding.UTF8.GetBytes(PolicyContext);
                }
            }
        }
        /// <summary>
        /// 取得客端存取政策的位元表示。
        /// </summary>
        public Byte[] PolicyContextBuffer { get; private set; }

        private TcpListener _Listener;
        private Thread _BackgroundWorker;
        /// <summary>
        /// 初始化 ClientAccessPolicyServer 的執行個體。
        /// </summary>
        public ClientAccessPolicyServer()
        {
            this.PolicyContext = "<?xml version=\"1.0\" encoding =\"utf-8\"?>\r\n<access-policy>\r\n  <cross-domain-access>\r\n";
            this.PolicyContext += "     <policy>\r\n      <allow-from>\r\n        <domain uri=\"*\" />\r\n      </allow-from>\r\n      <grant-to>\r\n";
            this.PolicyContext += "       <socket-resource port=\"4502-4534\" protocol=\"tcp\" />\r\n      </grant-to>\r\n    </policy>\r\n  </cross-domain-access>\r\n</access-policy>";

            _Listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 943);
            _BackgroundWorker = new Thread(new ThreadStart(BackgroundWork));
            _BackgroundWorker.IsBackground = true;
        }

        private void BackgroundWork()
        {
            while (true)
            {
                TcpClient m_Client = _Listener.AcceptTcpClient();
                MemoryStream m_LocalStream = new MemoryStream();
                NetworkStream m_NetworkStream = m_Client.GetStream();
                Byte[] m_Buffer = new Byte[1024];
                while (m_NetworkStream.DataAvailable)
                {
                    int m_Count = m_NetworkStream.Read(m_Buffer, 0, m_Buffer.Length);
                    m_LocalStream.Write(m_Buffer, 0, m_Count);
                }

                if (Encoding.UTF8.GetString(m_LocalStream.ToArray()) == REQUEST_STR)
                    m_NetworkStream.Write(this.PolicyContextBuffer, 0, this.PolicyContextBuffer.Length);

                m_LocalStream.Close();
                m_NetworkStream.Close();
                m_Client.Close();
            }
        }

        /// <summary>
        /// 啟動PolicyServer服務,若服務已經啟用則無作用。
        /// </summary>
        public void Start()
        {
            _Listener.Start();

            if (!_BackgroundWorker.IsAlive)
            {
                if 
                    (
                    _BackgroundWorker.ThreadState == ThreadState.Stopped || 
                    _BackgroundWorker.ThreadState == ThreadState.Aborted ||
                    _BackgroundWorker.ThreadState == ThreadState.AbortRequested
                    )
                {
                    _BackgroundWorker = new Thread(new ThreadStart(BackgroundWork));
                    _BackgroundWorker.IsBackground = true;
                }
                try { _BackgroundWorker.Start(); }
                catch
                {
                    _BackgroundWorker = new Thread(new ThreadStart(BackgroundWork));
                    _BackgroundWorker.IsBackground = true;
                    _BackgroundWorker.Start();
                }
            }
        }

        /// <summary>
        /// 終止PolicyServer服務,若要再次啟動必須呼叫Start方法。
        /// </summary>
        public void Abort()
        {
            if (_BackgroundWorker.IsAlive)
                _BackgroundWorker.Abort();

            _Listener.Stop();
            _Listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 943);
        }
    }
}

分享