views:

80

answers:

1

I basically try to reproduce the Socket example from here: http://www.silverlightshow.net/items/Sockets-and-their-implementation-in-SL2-Beta-1-including-a-chat-like-example.aspx I only made a small change in the client side, i.e.,

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

Then I got this permission error? Any idea why?

Unhandled Error in Silverlight Application An attempt was made to access a socket in a way forbidden by its access permissions.

+1  A: 

I believe that the way the socket security checks work you need to use the same url string that your application uses. to make sure i am using the correct string i have always used this to construct my 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);

I have used this exact code in a similar chat application. By using the Application.Current.Host.Source.DnsSafeHost Property you ensure that you are using the same Dns Name to access the server with the socket that the browser is using for HttpRequests.

Also are you serving the access policy file on port 943, this is another requirement of the socket support in Silverlight.

EDIT

To Confirm that you are serving the policy file you can do a number of things.

  1. install Fiddler, you can use it to debug all http traffic hitting your server, you should be able to see the request for the policy file.
  2. serve your policy file dynamically and then set a break point in your server application to confirm that it is being served. this is what i did.

here is the code i used to serve the policy file:

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

Then to use it:

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

I hosted this "server" in the same process that was running the rest of the Chat Server component. Set a breakpoint in HandleClient to confirm if it is receiving the request.

luke
My code is exactly the same as yours, but still gives me the same error. I manually created a clientaccesspolicy.xml and put into the default IIS folder, so it is served under 80 port. How to I move it to 943 port? Creating a new site?
Yang
[Edit] I manaully created a site with port 943 and moved the policy file there. It still doesn't work...
Yang
can you confirm that the client is succesfully receiving the policy file using a network debugger?
luke
Luke, can you give me a pointer how to do it?
Yang
Thanks Luke, it works!
Yang