Silverlight与自托管WCF使用TCP双工通信
“跨域访问”问题
异常信息
未能连接到 net.tcp://localhost:4503/IMyService。连接尝试的持续时间为 00:00:00.3300189。TCP 错误代码 10013: 试图以其访问权限所禁止的方式访问套接字。。原因可能是,试图以跨域的方式访问某服务,而该服务的配置不支持跨域访问。您可能需要与服务的所有者联系,以公开通过 HTTP 的套接字跨域策略,并在允许的套接字端口范围 4502-4534 之内承载该服务。
解决
让客户端能以“http://<<YourNetTcpIPAddress>>:80/clientaccesspolicy.xml”方式访问到跨域访问配置。
跨域配置内容
<?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*" /> </allow-from> <grant-to> <socket-resource port="4502-4534" protocol="tcp" /> </grant-to> </policy> </cross-domain-access> </access-policy>
解决方案
ClientCrossDomainAccessPolicy类
using System; using System.IO; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Web; using System.Text; public static class ClientCrossDomainAccessPolicy { [ServiceContract] public interface IPolicy { //确定可以访问“http://localhost:80/clientaccesspolicy.xml" [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")] Stream GetSilverlightPolicy(); //确定可以访问“http://localhost:80/crossdomain.xml" [OperationContract, WebGet(UriTemplate = "/crossdomain.xml")] Stream GetFlashPolicy(); } class Policy : IPolicy { #region IClientAccessPolicy Members Stream StringToStream(string result) { var oc = WebOperationContext.Current; if (oc == null) throw new NullReferenceException("WebOperationContext"); oc.OutgoingResponse.ContentType = "application/xml"; return new MemoryStream(Encoding.UTF8.GetBytes(result)); } public Stream GetSilverlightPolicy() { const string result = @"<?xml version=""1.0"" encoding=""utf-8""?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers=""*""> <domain uri=""*""/> </allow-from> <grant-to> <socket-resource port=""4502-4534"" protocol=""tcp"" /> </grant-to> </policy> </cross-domain-access> </access-policy>"; return StringToStream(result); } public Stream GetFlashPolicy() { const string result = @"<?xml version=""1.0""?> <!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd""> <cross-domain-policy> <allow-access-from domain=""*"" /> </cross-domain-policy>"; return StringToStream(result); } #endregion } public static ServiceHost GetHost() { var policyHost = new ServiceHost(typeof(Policy), new Uri("http://localhost:80"));//端口必须为80。若非TCP,像如HTTP托管,则直接将Policy发布至根下即可 policyHost.AddServiceEndpoint(typeof(IPolicy), new WebHttpBinding(), string.Empty).Behaviors.Add(new WebHttpBehavior()); return policyHost; } }
使用方式
///////////////////////////////////////////////// //加上以下三行以解决Silverlight跨域访问问题。实现效果:可以直接访问“http://localhost:80/clientaccesspolicy.xml"与“http://localhost:80/crossdomain.xml"读取跨域授权配置文件 using (var policyHost = ClientCrossDomainAccessPolicy.GetHost()) { policyHost.Open(); //写你自己的代码...
效果截图
参考
Using Silverlight 4 and Net.TCP Duplex Callbacks
示例代码下载
勉強心を持てば、生活は虚しくない!