在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號端點傳送
[完整範例程式碼下載: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);
}
}
}