Skip to main content
Home Forums Silverlight Programming Programming with .NET - General sockets with Silverlight 2 and java
16 replies. Latest Post by BigTundra on October 7, 2008.
(0)
elenabcn
Member
0 points
3 Posts
09-10-2008 9:59 AM |
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
Psychlis...
Contributor
6045 points
973 Posts
09-10-2008 10:54 AM |
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
09-10-2008 11:17 AM |
Thanks, it's working!!!
BigTundra
48 points
36 Posts
09-18-2008 9:38 AM |
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); }
09-18-2008 9:48 AM |
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)?
09-18-2008 4:21 PM |
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
09-18-2008 4:34 PM |
Crap...so I was just reading is the policy server on port 943 at the destination that you are creating the connection to?
09-18-2008 10:20 PM |
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.
09-19-2008 8:23 AM |
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.
09-19-2008 9:21 AM |
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.
09-19-2008 1:28 PM |
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.
09-19-2008 1:37 PM |
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?
09-19-2008 2:13 PM |
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!!
dejavudesi
2 points
4 Posts
10-02-2008 12:54 PM |
thank you Psychlist1972..you da man cheers!
10-06-2008 2:31 PM |
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>
Any help will be greatly appreciated! Thanks for everyone's time.
10-07-2008 4:08 AM |
10-07-2008 9:18 AM |
Thanks for the reply...I've tried it both ways and neither seems to make a difference.