1

我有一个本地托管的 WCF 服务和一个与之通信的 silverlight 5 应用程序。默认情况下,silverlight 在调用 WCF 服务时尝试通过 HTTP 获取跨域策略文件。我需要对此进行更改,以便改为通过 net.tcp 端口 943 提供策略文件。

我已经设置了一个本地 tcp 侦听器,它通过端口 943 提供策略文件,并且我遵循了这种技术,即我建立了一个虚拟套接字连接,以便通过 tcp 获取策略文件,因为它在每个应用程序生命周期中只检索一次。tcp 服务器按预期被命中,我得到的SocketError属性值是Success(尽管我必须注意,在启动侦听器后我第一次命中 tcp 服务器时,结果总是拒绝访问)。

据我所知,策略文件无效,因为 silverlight 应用程序仍然无法连接,或者上述技术不适用于 silverlight 5。

我想知道的是我正在做的事情是否可行并且我做得正确,否则是否有另一种方法可以通过 tcp 成功下载策略文件并消除通过 HTTP 检索它的需要。

谢谢

4

1 回答 1

1

我写了一篇关于在 WPF 中托管 silverlight 的长文章 - 并在此处使用带有 http 侦听器的 WCF:

如何在 WPF 4 应用程序中托管 Silverlight 4 应用程序?

现在虽然没有直接回答您的问题,但它确实展示了如何创建策略文件的 http 版本。

我还写了一些通过端口 943 提供策略侦听器的东西,但我找不到我发布源的位置 - 所以我会继续挖掘。据我记得,silverlight 对策略文件进行级联查找,如果它没有在端口 80 上获得连接,那么它将在端口 943 上查找。

我希望这对某处有所帮助。

好的,这是我为 net.TCP 传输而不是基于 HTTP 的策略侦听器。我想你现在已经整理好了,抱歉耽搁了。它现在可能对其他人有用。

我一直在寻找 MS 的东西,它说它们从 HTTP 级联到 TCP,但是,我不能,因此不得不假设它是双层的,然后改变了。

无论哪种方式,如果您使用 net.TCP 服务进行调用,并且想要一个监听器,这段代码应该会有所帮助:

#region "Policy Listener"

// This is a simple policy listener
// that provides the cross domain policy file for silverlight applications
// this provides them with a network access policy
public class SocketPolicyListener
{

    private TcpListener listener = null;
    private TcpClient Client = null;
    byte[] Data;
    private NetworkStream netStream = null;

    private string listenaddress = "";

    // This could be read from a file on the disk, but for now, this gives the silverlight application
    // the ability to access any domain, and all the silverlight ports 4502-4534
    string policyfile = "<?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>";

    // the request that we're expecting from the client
    private string _policyRequestString = "<policy-file-request/>";

    // Listen for our clients to connect
    public void Listen(string ListenIPAddress)
    {
        listenaddress = ListenIPAddress;
        if (listener == null)
        {
            listener = new TcpListener(IPAddress.Parse(ListenIPAddress), 943);

            // Try and stop our clients from lingering, keeping the socket open:
            LingerOption lo = new LingerOption(true, 1);
            listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger,lo);
        }

        listener.Start();

        WaitForClientConnect();
    }

    private void WaitForClientConnect()
    {
        listener.BeginAcceptTcpClient(new AsyncCallback(OnClientConnected), listener);
    }

    public void StopPolicyListener()
    {
        if (Client.Connected)
        {
            // Should never reach this point, as clients
            // are closed if they request the policy
            // only clients that open the connection and
            // do not submit a policy request will remain unclosed
            Client.Close();
        }

        listener.Stop();
    }

    public void RestartPolicyListener()
    {
        listener.Start();
    }

    // When a client connects:
    private void OnClientConnected(IAsyncResult ar)
    {
        if (ar.IsCompleted)
        {
            // Get the listener that handles the client request.
            TcpListener listener = (TcpListener)ar.AsyncState;

            // End the operation and display the received data on 
            // the console.
            Client = listener.EndAcceptTcpClient(ar);

            // Try and stop our clients from lingering, keeping the socket open:
            LingerOption lo = new LingerOption(true, 1);
            Client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);

            // Set our receive callback     
            Data = new byte[1024];
            netStream = Client.GetStream();
            netStream.BeginRead(Data, 0, 1024, ReceiveMessage, null);
        }

        WaitForClientConnect();
    }

    // Read from clients.
    public void ReceiveMessage(IAsyncResult ar)
    {
        int bufferLength;
        try
        {
            bufferLength = Client.GetStream().EndRead(ar);

            // Receive the message from client side.
            string messageReceived = Encoding.ASCII.GetString(Data, 0, bufferLength);

            if (messageReceived == _policyRequestString)
            {
                // Send our policy file, as it's been requested
                SendMessage(policyfile);

                // Have to close the connection or the
                // silverlight client will wait around.
                Client.Close();
            }
            else
            {
                // Continue reading from client. 
                Client.GetStream().BeginRead(Data, 0, Data.Length, ReceiveMessage, null);
            }
        }
        catch (Exception ex)
        {
            throw new Exception(Client.Client.RemoteEndPoint.ToString() + " is disconnected.");
        }
    }

    // Send the message.
    public void SendMessage(string message)
    {
        try
        {
            byte[] bytesToSend = System.Text.Encoding.ASCII.GetBytes(message);
            //Client.Client.Send(bytesToSend,SocketFlags.None);
            Client.GetStream().Write(bytesToSend,0, bytesToSend.Length);
            Client.GetStream().Flush();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}
#endregion
于 2013-04-03T09:39:44.967 回答