2010-05-20 125 views
2

試圖調用WCF通過Silverlight的一個NetTcpBinding的,我得到的錯誤:Silverlight的WCF NetTcpBinding的問題

「TCP錯誤代碼10013:試圖通過其訪問權限不允許的方式來訪問一個插座..這可能是因爲嘗試以跨域方式訪問服務,而服務未配置爲跨域訪問。您可能需要聯繫服務的所有者以通過HTTP公開跨域策略套接字並將該服務託管在允許的套接字端口範圍4502-4534中。「

我的WCF服務託管在IIS7,勢必:

http://localhost.myserivce.com端口80 和的net.tcp端口4502

我可以看到,如果http://localhost.myserivce.com/myservice.svc我瀏覽到它(我的hosts文件指向這個域到localhost)。 我還可以看到http://localhost.myserivce.com/clientaccesspolicy.xml

<?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="4502-4534" protocol="tcp" /> 
     </grant-to> 
     </policy> 
    </cross-domain-access> 
</access-policy> 

我在做什麼錯?

回答

1

如果您嘗試在端口範圍4502-4534中建立TCP連接,Silverlight將首先在端口943上發佈請求以檢索客戶端訪問策略文件內容 - 它不會讀取http://localhost.myserivce.com/clientaccesspolicy.xml處的文件,因爲這是僅用於HTTP請求。 您需要將服務器配置爲偵聽TCP端口943,期望請求字符串等於<policy-file-request/>並回復xml文件內容。

下面的代碼顯示了一個基本的實現,您需要使用端口943來傳遞給本地IPEndPoint:

public class SocketPolicyServer 
{ 
    private const string m_policyRequestString = "<policy-file-request/>"; 
    private string m_policyResponseString; 
    private TcpListener m_listener; 
    bool _started = false; 

    public SocketPolicyServer() 
    { 
     m_policyResponseString = File.ReadAllText("path/to/clientaccesspolicy.xml"); 
    } 

    public void Start(IPEndPoint endpoint) 
    { 
     m_listener = new TcpListener(endpoint); 
     m_listener.Start(); 
     _started = true; 
     m_listener.BeginAcceptTcpClient(HandleClient, null); 
    } 

    public event EventHandler ClientConnected; 
    public event EventHandler ClientDisconnected; 

    private void HandleClient(IAsyncResult res) 
    { 
     if(_started) 
     { 
      try 
      { 
       TcpClient client = m_listener.EndAcceptTcpClient(res); 
       m_listener.BeginAcceptTcpClient(HandleClient, null); 
       this.ProcessClient(client); 
      } 
      catch(Exception ex) 
      { 
       Trace.TraceError("SocketPolicyServer : {0}", ex.Message); 
      } 
     } 
    } 

    public void Stop() 
    { 
     _started = false; 
     m_listener.Stop(); 
    } 

    public void ProcessClient(TcpClient client) 
    { 
     try 
     { 
      if(this.ClientConnected != null) 
       this.ClientConnected(this, EventArgs.Empty); 

      StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8); 
      char[] buffer = new char[m_policyRequestString.Length]; 
      int read = reader.Read(buffer, 0, buffer.Length); 

      if(read == buffer.Length) 
      { 
       string request = new string(buffer); 

       if(StringComparer.InvariantCultureIgnoreCase.Compare(request, m_policyRequestString) == 0) 
       { 
        StreamWriter writer = new StreamWriter(client.GetStream()); 
        writer.Write(m_policyResponseString); 
        writer.Flush(); 
       } 
      } 
     } 
     catch(Exception ex) 
     { 
      Trace.TraceError("SocketPolicyServer : {0}", ex.Message); 
     } 
     finally 
     { 
      client.GetStream().Close(); 
      client.Close(); 
      if(this.ClientDisconnected != null) 
       this.ClientDisconnected(this, EventArgs.Empty); 
     } 
    } 
} 
4

這種情況已經改變爲SL4 RTM的。 SL4的net.tcp客戶端不會在tcp 943上查找客戶端訪問策略,而是會使用舊的方法來使用web服務器的根,端口80.奇怪的是,這在任何地方都沒有很好的記錄,但我可以確認這是發佈的行爲。

底線,從SL4 RTM開始,您描述的方法應該可行,而其他答案則不適用。