Проблема с Silverlight WCF netTcpBinding - PullRequest
2 голосов
/ 20 мая 2010

Пытаясь вызвать WCF с помощью netTcpBinding через Silverlight, я получаю сообщение об ошибке:

"Код ошибки 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>

Что я делаю не так?

Ответы [ 2 ]

4 голосов
/ 01 марта 2011

Это изменилось с SL4 RTM. Клиент SL4 net.tcp не будет искать политику клиентского доступа на TCP 943, но вместо этого будет использовать старый метод использования корня веб-сервера, порт 80. Как ни странно, это не очень хорошо документировано в любом месте, но я могу подтвердите, что это поведение на момент выпуска.

В итоге, начиная с SL4 RTM, метод, который вы описываете, должен работать, а другой ответ здесь не работает.

1 голос
/ 17 июня 2010

Если вы попытаетесь установить TCP-соединение в диапазоне портов 4502-4534, Silverlight сначала отправит запрос на порт 943 для получения содержимого файла политики клиентского доступа - он не будет читать файл на http://localhost.myserivce.com/clientaccesspolicy.xml, потому что это только для HTTP-запросов. Вам необходимо настроить сервер на прослушивание TCP-порта 943, ожидать строку запроса равную <policy-file-request/> и отвечать содержимым файла xml.

Приведенный ниже код демонстрирует базовую реализацию, вам нужно передать его локальному IPEndPoint через порт 943:

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);
        }
    }
}
...