Silverlight套接字:Silverlight应用程序中的未处理错误尝试以其访问权限禁止的方式访问套接字

时间:2010-06-07 22:51:48

标签: silverlight sockets tcp

我基本上尝试从这里重现Socket示例:http://www.silverlightshow.net/items/Sockets-and-their-implementation-in-SL2-Beta-1-including-a-chat-like-example.aspx 我只在客户端做了一点改动,即

 String safeHost = "127.0.0.1";
            int port = 4509;

然后我收到了这个权限错误?知道为什么吗?

Silverlight应用程序中的未处理错误尝试以其访问权限禁止的方式访问套接字。

1 个答案:

答案 0 :(得分:3)

我相信套接字安全检查的工作方式,您需要使用应用程序使用的相同url字符串。为了确保我使用正确的字符串我一直用它来构建我的DNSEndPoint:

int Port = 4509;
DnsEndPoint ep = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, Port, AddressFamily.InterNetwork);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sock.NoDelay = true;
SocketAsyncEventArgs ea = new SocketAsyncEventArgs{RemoteEndPoint  = ep};
//set up completed event handler et al.
sock.ConnectAsync(ea);

我在类似的聊天应用程序中使用了这个确切的代码。通过使用Application.Current.Host.Source.DnsSafeHost属性,您可以确保使用相同的Dns名称来访问具有浏览器用于HttpRequests的套接字的服务器。

您还在端口943上提供访问策略文件,这是Silverlight中套接字支持的另一个要求。

修改

要确认您正在为策略文件提供服务,您可以执行许多操作。

  1. 安装Fiddler,您可以使用它来调试命中服务器的所有http流量,您应该能够看到对策略文件的请求。
  2. 动态提供策略文件,然后在服务器应用程序中设置断点以确认它正在提供服务。这就是我所做的。
  3. 这是我用来提供策略文件的代码:

    public abstract class Server
    {
        protected Socket Listener { get; set; }
        protected int Port { get; private set; }
        protected int Backlog { get; private set; }
        protected bool isStopped { get; set; }
        protected SocketAsyncEventArgs AcceptArgs {get;set;}
    
        public Server(int port)
        {
            AcceptArgs = new SocketAsyncEventArgs();
            AcceptArgs.Completed += new EventHandler<SocketAsyncEventArgs>(Accept_Completed);
            isStopped = true;
            Port = port;
            Backlog = 100;
        }
    
    
        public Server(int port, int backlog)
        {
            isStopped = true;
            Port = port;
            Backlog = backlog;
        }
    
        public void Start()
        {
            isStopped = false;
    
            Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ep = new IPEndPoint(IPAddress.Any, Port);
            Listener.ExclusiveAddressUse = true;
            Listener.Bind(ep);
            //Console.WriteLine("Listening on " + Port);
            Listener.Listen(Backlog);
    
            Listener.AcceptAsync(AcceptArgs);
        }
    
        void Accept_Completed(object sender, SocketAsyncEventArgs e)
        {
            if (isStopped) return;
            Socket client = e.AcceptSocket;
            //Console.WriteLine("Accepted Connection From: " + client.RemoteEndPoint.ToString());
            e.AcceptSocket = null;
            Listener.AcceptAsync(AcceptArgs);
            HandleClient(client);
        }
    
        public virtual void Stop()
        {
            if (isStopped) throw new InvalidOperationException("Server already Stopped!");
            isStopped = true;
            try
            {
                Listener.Shutdown(SocketShutdown.Both);
                Listener.Close();
            }
            catch (Exception)
            {
            }
        }
    
        protected abstract void HandleClient(Socket Client);
    }
    public class PolicyServer : Server
    {
        public const String policyStr = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
                                            <access-policy>
                                                <cross-domain-access>
                                                    <policy>
                                                        <allow-from>
                                                            <domain uri=""*"" />
                                                        </allow-from>
                                                        <grant-to>
                                                            <socket-resource port=""4530"" protocol=""tcp"" />
                                                        </grant-to>
                                                    </policy>
                                                </cross-domain-access>
                                            </access-policy>";
        private byte[] policy = Encoding.ASCII.GetBytes(policyStr);
        private static string policyRequestString = "<policy-file-request/>";
    
        public PolicyServer(): base(943)
        {
        }
    
        protected override void HandleClient(Socket socket)
        {
            TcpClient client = new TcpClient { Client = socket };
            Stream s = client.GetStream();
            byte[] buffer = new byte[policyRequestString.Length];
            client.ReceiveTimeout = 5000;
            s.Read(buffer, 0, buffer.Length);//read in the request string, but don't do anything with it
                                                         //you could confirm that it is equal to the policyRequestString
            s.Write(policy, 0, policy.Length);
            s.Flush();
    
            socket.Shutdown(SocketShutdown.Both);
            socket.Close(1);
            client.Close();
        }
    }
    

    然后使用它:

    PolicyServer ps = new PolicyServer();
    ps.Start();
    //then when shutting down
    ps.Stop();
    

    我在运行Chat Server组件其余部分的同一进程中托管了这个“服务器”。在HandleClient中设置断点以确认它是否正在接收请求。