Page view counter
sockets with Silverlight 2 and java
Last post 10-07-2008 9:18 AM by BigTundra. 16 replies.
Sort Posts:
09-10-2008 9:59 AM
sockets with Silverlight 2 and java

Hello 

 I'm trying to connect an application done with  version Silverlight 2 Beta 2  with another one in java using sockets.

The java application acts as server:

    ServerSocket   dateServer = new ServerSocket(4503);
    Socket client = dateServer.accept();
    System.out.println("Accepted a connection from: "+client.getInetAddress());

 When I do a telnet 127.0.0.1 4503 the java application receives the connection.

 The silverligh application is the client:

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            args.UserToken = socket;
            args.RemoteEndPoint = new DnsEndPoint(Application.Current.Host.Source.DnsSafeHost, 4503);
            args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSocketConnectCompleted);
            socket.ConnectAsync(args);
     

        private void OnSocketConnectCompleted(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                byte[] response = new byte[1024];
                e.SetBuffer(response, 0, response.Length);
                e.Completed -= new EventHandler<SocketAsyncEventArgs>(OnSocketConnectCompleted);
                e.Completed += new EventHandler<SocketAsyncEventArgs>(OnSocketReceive);
                Socket socket = (Socket)e.UserToken;
                socket.ReceiveAsync(e);
            }
        }
 

Java and Silverlight are deployed in the same computer and everything runs in the local computer.

There is no cross-domain, but just in case, I've got a http://127.0.0.1:8080/clientaccesspolicy.xml allowing all access.

 In the   OnSocketConnectCompleted method I allways receive an  SocketError with AccessDenied. 

Has anyone any clue why??

 Thank you very much

Elena

elenabcn

Loading...
Joined on 09-10-2008
Posts 3
09-10-2008 10:54 AM
Marked as Answer
Socket Policy Server (was Re: sockets with Silverlight 2 and java)

The clientaccesspolicy.xml won't come into play, as this is sockets. If you think about it, you are never guaranteed to have a web server on the same machine as your socket server. When you consider port *all* calls are "cross domain" conceptually.

So, what the Silverlight team did in Beta 2 was require, for 100% of the scenarios, a policy server running on port 943 which serves up a slightly different crossdomain xml file.

There's a brief description on Tim Heuer's blog.

Here's an example policy file:

<?xml version="1.0" encoding ="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="*" />
      </allow-from>
      <grant-to>
        <socket-resource port="4532" protocol="tcp" />
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy> 

And here's code that serves it up from a console app (taken from a chat application demo I did):

(Program.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PolicyServer
{
    class Program
    {
        static void Main(string[] args)
        {
            PolicySocketServer server = new PolicySocketServer();
            server.StartSocketServer();

        }
    }

 

(PolicySocketServer.cs - shamelessly snagged from the URL below)

// Code from http://weblogs.asp.net/dwahlin/archive/2008/06/08/creating-a-silverlight-2-client-access-policy-socket-server.aspx

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Reflection;
using System.Configuration;

namespace PolicyServer
{
    class PolicySocketServer
    {
        TcpListener _Listener = null;
        TcpClient _Client = null;
        static ManualResetEvent _TcpClientConnected = new ManualResetEvent(false);
        const string _PolicyRequestString = "<policy-file-request/>";
        int _ReceivedLength = 0;
        byte[] _Policy = null;
        byte[] _ReceiveBuffer = null;

        private void InitializeData()
        {
            string policyFile = ConfigurationManager.AppSettings["PolicyFilePath"];
            using (FileStream fs = new FileStream(policyFile, FileMode.Open))
            {
                _Policy = new byte[fs.Length];
                fs.Read(_Policy, 0, _Policy.Length);
            }
            _ReceiveBuffer = new byte[_PolicyRequestString.Length];
        }

        public void StartSocketServer()
        {
            InitializeData();

            try
            {
                //Using TcpListener which is a wrapper around a Socket
                //Allowed port is 943 for Silverlight sockets policy data
                _Listener = new TcpListener(IPAddress.Any, 943);
                _Listener.Start();
                Console.WriteLine("Policy server listening...");
                while (true)
                {
                    _TcpClientConnected.Reset();
                    Console.WriteLine("Waiting for client connection...");
                    _Listener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAccept), null);
                    _TcpClientConnected.WaitOne(); //Block until client connects
                }
            }
            catch (Exception exp)
            {
                LogError(exp);
            }
        }

        private void OnBeginAccept(IAsyncResult ar)
        {
            _Client = _Listener.EndAcceptTcpClient(ar);
            _Client.Client.BeginReceive(_ReceiveBuffer, 0, _PolicyRequestString.Length, SocketFlags.None,
                new AsyncCallback(OnReceiveComplete), null);
        }

        private void OnReceiveComplete(IAsyncResult ar)
        {
            try
            {
                _ReceivedLength += _Client.Client.EndReceive(ar);
                //See if there's more data that we need to grab
                if (_ReceivedLength < _PolicyRequestString.Length)
                {
                    //Need to grab more data so receive remaining data
                    _Client.Client.BeginReceive(_ReceiveBuffer, _ReceivedLength,
                        _PolicyRequestString.Length - _ReceivedLength,
                        SocketFlags.None, new AsyncCallback(OnReceiveComplete), null);
                    return;
                }

                //Check that <policy-file-request/> was sent from client
                string request = System.Text.Encoding.UTF8.GetString(_ReceiveBuffer, 0, _ReceivedLength);
                if (StringComparer.InvariantCultureIgnoreCase.Compare(request, _PolicyRequestString) != 0)
                {
                    //Data received isn't valid so close
                    _Client.Client.Close();
                    return;
                }
                //Valid request received....send policy data
                _Client.Client.BeginSend(_Policy, 0, _Policy.Length, SocketFlags.None,
                    new AsyncCallback(OnSendComplete), null);
            }
            catch (Exception exp)
            {
                _Client.Client.Close();
                LogError(exp);
            }
            _ReceivedLength = 0;
            _TcpClientConnected.Set(); //Allow waiting thread to proceed
        }

        private void OnSendComplete(IAsyncResult ar)
        {
            try
            {
                _Client.Client.EndSendFile(ar);
            }
            catch (Exception exp)
            {
                LogError(exp);
            }
            finally
            {
                //Close client socket
                _Client.Client.Close();
            }
        }

        private void LogError(Exception exp)
        {
            string appFullPath = Assembly.GetCallingAssembly().Location;
            string logPath = appFullPath.Substring(0, appFullPath.LastIndexOf("\\")) + ".log";
            StreamWriter writer = new StreamWriter(logPath, true);
            try
            {
                writer.WriteLine(logPath,
                    String.Format("Error in PolicySocketServer: "
                    + "{0} \r\n StackTrace: {1}", exp.Message, exp.StackTrace));
            }
            catch { }
            finally
            {
                writer.Close();
            }
        }
    }
}

 

Pete

If your question was answered, please mark the response as the answer.

Silverlight.net Moderator
MVP: Visual Developer - Client Application Development
POKE 53280,0 - My Blog

Psychlist1972

Loading...
Joined on 10-12-2004
Maryland, USA
Posts 833
09-10-2008 11:17 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

Smile  Thanks, it's working!!!

elenabcn

Loading...
Joined on 09-10-2008
Posts 3
09-18-2008 9:38 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 Hi,

I'm trying to get sockets to work and I keep getting the AccessDenied SocketError.  I've implemented the policyserver, but nothing ever connects to it when I run my Silverlight socket code.  I'm trying to do this in a virtual machine with a 192.168 address and port I'm trying to connect to is a 10. address port 4502.  Is this why I'm having problems?  I can ping and connect to that port from within the virtual machine just not with Silverlight.

Thanks for your help

 

 

public AgTelnet()
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            args.RemoteEndPoint = new IPEndPoint(IPAddress.Parse("10.8.104.81"),4502);
            args.UserToken = s;
            args.Completed += new EventHandler(args_Completed);
            s.ConnectAsync(args);
        }

        void args_Completed(object sender, SocketAsyncEventArgs e)
        {
            if (e.SocketError != null)
            {
                string s = "";
            }
            int i = e.BytesTransferred;
            byte[] response = new byte[1024];
            e.SetBuffer(response, 0, response.Length);
            e.Completed -=
              new EventHandler(args_Completed);
            e.Completed += new EventHandler(OnSocketReceive);
            Socket socket = (Socket)e.UserToken;
            socket.ReceiveAsync(e);

        }
  
BigTundra

Loading...
Joined on 09-05-2007
Posts 33
09-18-2008 9:48 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

Let's check the simple stuff first.

Have you verified that no software or hardware firewalls are blocking this call from within the browser?  You can't really ping a specific port, so are you sure you got through?

Did you try to get through to port 943 (the policy server)?

Pete

If your question was answered, please mark the response as the answer.

Silverlight.net Moderator
MVP: Visual Developer - Client Application Development
POKE 53280,0 - My Blog

Psychlist1972

Loading...
Joined on 10-12-2004
Maryland, USA
Posts 833
09-18-2008 4:21 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

Ok...so I turned off windows firewall just to make sure it's not blocking.

 I connected to the policy server using IE http://localhost:943 and it connected hit my break point etc.  So that seems to be working.

I know I can get to that port on the outside 10.8... box because it's a telnet session running on the other end so I was able to telnet into it from my virtual machine.

Now this policy server is running on port 943 I'm confused as to how Silverlight uses it.  If it blocks all but ports 4502-4534 then what is accessing the policy server?  

What's next :)

 Thanks!

 Shane

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
09-18-2008 4:34 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 Crap...so I was just reading is the policy server on port 943 at the destination that you are creating the connection to?

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
09-18-2008 10:20 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

Yep. Silveright will contact the 10.8. whatever : 943 address to look for the policy before it connects to the 4502 endpoint at the same address.

The policy server controls access at the server. Think of it this way: you, as the server owner, want to control what ports you'll allow access to and from where, so you serve up a policy file. This is very similar to the client access policy on a web site - the server owns it.

The policy server needs to be a non-silverlight app running on the same ip (or dns address) as your socket server.

Pete

If your question was answered, please mark the response as the answer.

Silverlight.net Moderator
MVP: Visual Developer - Client Application Development
POKE 53280,0 - My Blog

Psychlist1972

Loading...
Joined on 10-12-2004
Maryland, USA
Posts 833
09-19-2008 8:23 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 Is this something that is going to change when they release.  Because it might be a deal breaker for me to use silverlight, because the device I'm connecting to isn't a webserver it just supports a telnet connection.  I can't make it provide a policy file on port 943.

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
09-19-2008 9:21 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

I wouldn't expect it to be. It was put in specifically because socket servers often don't exist on the same machines as web servers. The Port 943 Policy Server is a security precaution, required in order to keep Silverlight a safe and trusted platform for internet applications.

If you need to get access to a resource that can't support the addition of a policy server, you will need to build a proxy service. That's a socket (and policy) server on a machine you can control, which then uses the regular .NET (or other) stack to communicate with your telnet server and forward packets from and to Silverlight.

Pete

If your question was answered, please mark the response as the answer.

Silverlight.net Moderator
MVP: Visual Developer - Client Application Development
POKE 53280,0 - My Blog

Psychlist1972

Loading...
Joined on 10-12-2004
Maryland, USA
Posts 833
09-19-2008 1:28 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 That's a bummer that security may get in the way of us being able to do something really cool.    I sent this info to my manager and he sent me a link to Flex 3.... uggh.

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
09-19-2008 1:37 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

If you can control the port number so that it is in the 4500 range, are you sure you can't also run a policy server?

Pete

If your question was answered, please mark the response as the answer.

Silverlight.net Moderator
MVP: Visual Developer - Client Application Development
POKE 53280,0 - My Blog

Psychlist1972

Loading...
Joined on 10-12-2004
Maryland, USA
Posts 833
09-19-2008 2:13 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 Anythings possible ;) ...I'm going down that road now.  But it's more like a winding mountain road than the information super highway I was trying to get on.  :)

 

Anyway thanks for your help Pete!!

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
10-02-2008 12:54 PM
Yes [Y]Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 thank you Psychlist1972..you da man Yes Beer cheers!

dejavudesi

Loading...
Joined on 10-02-2008
Posts 4
10-06-2008 2:31 PM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 So I have my policy file server implemented, but I'm still getting access denied when I try the socket connection.  I put a packet sniffer on the connection I can see the request go out and the policy file returned, but from that point I'm at a loss as to why I'm being denied.

Here is my policy file: 

<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 only other thing that I can think of is if the AccessDenied has something to do with internet zones in windows, because I'm in a VM that is running on a 192.168 address and connecting to 10. address.  I've setup http://localhost,http://10.8.104.81 and 10.8.104.81 as both being in my intranet zone which allowed me to use Http communication to the device, but the socket stuff still isn't working.

  Any help will be greatly appreciated!  Thanks for everyone's time.

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
10-07-2008 4:08 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 

In the line   <socket-resource port="4502-4534" protocol="tcp" />   put just the port that ju're using. In my case it didn't work writing here a rank of ports.
elenabcn

Loading...
Joined on 09-10-2008
Posts 3
10-07-2008 9:18 AM
Re: Socket Policy Server (was Re: sockets with Silverlight 2 and java)

 Thanks for the reply...I've tried it both ways and neither seems to make a difference.

BigTundra

Loading...
Joined on 09-05-2007
Posts 33
Microsoft Communities