Silverlight WCF绑定问题
尝试通过Silverlight调用具有netTcpBinding的WCF时,我收到错误: “TCP错误代码10013:试图以访问权限所禁止的方式访问套接字。。这可能是因为在服务未配置为跨域访问时,尝试以跨域方式访问服务。您可能需要联系服务的所有者,以通过HTTP公开套接字跨域策略,并在允许的套接字端口范围4502-4534内托管服务。” 我的WCF服务托管在IIS7中,绑定到: 在端口80上 和端口4502上的net.tcp 我可以查看是否浏览到它(我的hosts文件将此域指向localhost)。 我还可以看到:Silverlight WCF绑定问题,wcf,silverlight-4.0,nettcpbinding,clientaccesspolicy.xml,Wcf,Silverlight 4.0,Nettcpbinding,Clientaccesspolicy.xml,尝试通过Silverlight调用具有netTcpBinding的WCF时,我收到错误: “TCP错误代码10013:试图以访问权限所禁止的方式访问套接字。。这可能是因为在服务未配置为跨域访问时,尝试以跨域方式访问服务。您可能需要联系服务的所有者,以通过HTTP公开套接字跨域策略,并在允许的套接字端口范围4502-4534内托管服务。” 我的WCF服务托管在IIS7中,绑定到: 在端口80上 和端口4502上的net.tcp 我可以查看是否浏览到它(我的hosts文件将此域指向localhost
我做错了什么?如果您尝试在端口范围4502-4534中建立TCP连接,Silverlight将首先在端口943上发布请求以检索客户端访问策略文件内容-它不会在读取文件,因为这仅用于HTTP请求。 您需要将服务器配置为在TCP端口943上侦听,请求字符串应等于
,并使用xml文件内容进行回复
下面的代码显示了一个基本实现,您需要使用端口943将一个本地IPEndPoint传递给它:
public class SocketPolicyServer
{
private const string m_policyRequestString = "<policy-file-request/>";
private string m_policyResponseString;
private TcpListener m_listener;
bool _started = false;
public SocketPolicyServer()
{
m_policyResponseString = File.ReadAllText("path/to/clientaccesspolicy.xml");
}
public void Start(IPEndPoint endpoint)
{
m_listener = new TcpListener(endpoint);
m_listener.Start();
_started = true;
m_listener.BeginAcceptTcpClient(HandleClient, null);
}
public event EventHandler ClientConnected;
public event EventHandler ClientDisconnected;
private void HandleClient(IAsyncResult res)
{
if(_started)
{
try
{
TcpClient client = m_listener.EndAcceptTcpClient(res);
m_listener.BeginAcceptTcpClient(HandleClient, null);
this.ProcessClient(client);
}
catch(Exception ex)
{
Trace.TraceError("SocketPolicyServer : {0}", ex.Message);
}
}
}
public void Stop()
{
_started = false;
m_listener.Stop();
}
public void ProcessClient(TcpClient client)
{
try
{
if(this.ClientConnected != null)
this.ClientConnected(this, EventArgs.Empty);
StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8);
char[] buffer = new char[m_policyRequestString.Length];
int read = reader.Read(buffer, 0, buffer.Length);
if(read == buffer.Length)
{
string request = new string(buffer);
if(StringComparer.InvariantCultureIgnoreCase.Compare(request, m_policyRequestString) == 0)
{
StreamWriter writer = new StreamWriter(client.GetStream());
writer.Write(m_policyResponseString);
writer.Flush();
}
}
}
catch(Exception ex)
{
Trace.TraceError("SocketPolicyServer : {0}", ex.Message);
}
finally
{
client.GetStream().Close();
client.Close();
if(this.ClientDisconnected != null)
this.ClientDisconnected(this, EventArgs.Empty);
}
}
}
公共类SocketPolicyServer
{
私有常量字符串m_policyRequestString=“”;
私人字符串m_policyResponseString;
私人TcpListener m_监听器;
bool _start=false;
公共SocketPolicyServer()
{
m_policyResponseString=File.ReadAllText(“path/to/clientaccesspolicy.xml”);
}
公共无效起点(IPEndPoint终点)
{
m_侦听器=新的TcpListener(端点);
m_listener.Start();
_开始=真;
m_listener.BeginAcceptTcpClient(HandleClient,null);
}
公共事件事件处理程序ClientConnected;
公共事件事件处理程序ClientDisconnected;
私有无效HandleClient(IAsyncResult res)
{
如果(_已启动)
{
尝试
{
TcpClient client=m_listener.EndAcceptTcpClient(res);
m_listener.BeginAcceptTcpClient(HandleClient,null);
这个.ProcessClient(客户机);
}
捕获(例外情况除外)
{
Trace.TraceError(“SocketPolicyServer:{0}”,例如Message);
}
}
}
公共停车场()
{
_开始=错误;
m_listener.Stop();
}
public void ProcessClient(TcpClient客户端)
{
尝试
{
if(this.ClientConnected!=null)
this.ClientConnected(this,EventArgs.Empty);
StreamReader=新的StreamReader(client.GetStream(),Encoding.UTF8);
char[]buffer=new char[m_policyRequestString.Length];
int read=reader.read(buffer,0,buffer.Length);
if(读==缓冲区长度)
{
字符串请求=新字符串(缓冲区);
if(StringComparer.InvariantCultureIgnorCase.Compare(请求,m_policyRequestString)==0)
{
StreamWriter writer=新的StreamWriter(client.GetStream());
编剧:写作(m_policyResponseString);
writer.Flush();
}
}
}
捕获(例外情况除外)
{
Trace.TraceError(“SocketPolicyServer:{0}”,例如Message);
}
最后
{
client.GetStream().Close();
client.Close();
如果(this.ClientDisconnected!=null)
this.ClientDisconnected(this,EventArgs.Empty);
}
}
}
自SL4 RTM以来,这一点已发生变化。SL4 net.tcp客户端不会在tcp 943上查找客户端访问策略,而是使用旧方法使用Web服务器根端口80。奇怪的是,这在任何地方都没有很好的文档记录,但我可以确认这是发布时的行为
总之,对于SL4RTM,您描述的方法应该有效,而这里的另一个答案则无效
public class SocketPolicyServer
{
private const string m_policyRequestString = "<policy-file-request/>";
private string m_policyResponseString;
private TcpListener m_listener;
bool _started = false;
public SocketPolicyServer()
{
m_policyResponseString = File.ReadAllText("path/to/clientaccesspolicy.xml");
}
public void Start(IPEndPoint endpoint)
{
m_listener = new TcpListener(endpoint);
m_listener.Start();
_started = true;
m_listener.BeginAcceptTcpClient(HandleClient, null);
}
public event EventHandler ClientConnected;
public event EventHandler ClientDisconnected;
private void HandleClient(IAsyncResult res)
{
if(_started)
{
try
{
TcpClient client = m_listener.EndAcceptTcpClient(res);
m_listener.BeginAcceptTcpClient(HandleClient, null);
this.ProcessClient(client);
}
catch(Exception ex)
{
Trace.TraceError("SocketPolicyServer : {0}", ex.Message);
}
}
}
public void Stop()
{
_started = false;
m_listener.Stop();
}
public void ProcessClient(TcpClient client)
{
try
{
if(this.ClientConnected != null)
this.ClientConnected(this, EventArgs.Empty);
StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8);
char[] buffer = new char[m_policyRequestString.Length];
int read = reader.Read(buffer, 0, buffer.Length);
if(read == buffer.Length)
{
string request = new string(buffer);
if(StringComparer.InvariantCultureIgnoreCase.Compare(request, m_policyRequestString) == 0)
{
StreamWriter writer = new StreamWriter(client.GetStream());
writer.Write(m_policyResponseString);
writer.Flush();
}
}
}
catch(Exception ex)
{
Trace.TraceError("SocketPolicyServer : {0}", ex.Message);
}
finally
{
client.GetStream().Close();
client.Close();
if(this.ClientDisconnected != null)
this.ClientDisconnected(this, EventArgs.Empty);
}
}
}