Socket通讯时,报错“您的主机中的软件放弃了一个已建立的连接”

       最近一个项目需要使用C#编写一个服务器端与Flex的客户端进行通讯。与Flex Socket通讯必须要发送安全策略进行安全检查,而在 Adobe Flash Player 升级到 9.0.124 后,由于安全策略更改,原来 Socket 或 XmlSocket 的应用里的 http 方式加载安全策略的手段不能继续使用。Adobe Flash Player对于安全策略的更改如下:

     1、首先检测目标服务器的 843 端口是否提供安全策略;
     2、如果 1 没有检测到策略,则检测 actionscript 是否使用了 Security.loadPolicyFile(xmlsocket://)手段提供安全策略,如果还没检测到,则使用第 3 步检测;
     3、检测目标服务器目标端口是否提供安全策略。
  

      写好了程序,测试时,使用F5调试模式运行时,一切很顺利(为此偷偷地窃喜了一下,毕竟是第一次使用Socket)。但接下来问题就来了,我在使用Ctrl+F5运行程序时,就开始报错“您的主机中的软件放弃了一个已建立的连接”。这个报错一般不外乎就是两种情况:1、双方的协议不一致;2、缓存超时,会使Socket处于一种假死状态。可是查了半天资料,一点有用的资料都没有,头晕脑胀的。更郁闷的是为什么F5运行的结果和Ctrl+F5运行的结果不一样呢?

     问了一下Flex的开发人员,说是Flash Player 是用“\0”来做分隔符的。回头检查了代码:

public void PolicyListen()
        {
            //创建一个Socket用来监听943(固定的)端口的策略请求  
            socketPolicy = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socketPolicy.Bind(new IPEndPoint(IPAddress.Parse(strIPSys), 843));
                socketPolicy.Listen(10);
            }
            catch (Exception ex)
            {
                CreateLog.CreateTxt("监听和发送策略文件失败,请检查本系统IP是否正确!");
            }
                //无限循环监听
            while (true)
            {
                if (socketPolicy.Blocking)//如果Socket是阻止模式的
                {
                    //创建Socket,用来获取监听Socket的第一个Socket链接
                    _policy = socketPolicy.Accept();

                    //定义一个字符串,该字符串与Silverlight发送过来的请求字符串一样。
                    string policyRequestString = "";

                    //定义一个字节数组
                    byte[] b = new byte[policyRequestString.Length];

                    //将客户端发送过来,服务器接收到的字节数组存入b中
                    _policy.Receive(b);

                    //将接收到的字节数组转换成字符串
                    string requeststring = System.Text.Encoding.UTF8.GetString(b, 0, b.Length);

                    //比对客户端发送过来的字符串是否和之前定义的额定好的策略请求字符串相同,如果相同,说明该请求是一个策略请求。
                    if (requeststring == policyRequestString)
                    {
                        //如果客户端发送的是一个策略请求,服务器发送策略文件到客户端
                        SendPolicy(_policy);
                        //关闭当前连接Socket
                        _policy.Close();

                    }
                    else// 否则,显示错误
                    {
                        CreateLog.CreateTxt("监听和发送策略文件文件失败!");
                    }
                }
            }
        }

 

       发现这句:string policyRequestString = "";  //定义一个字符串,该字符串与Silverlight发送过来的请求字符串一样。    没有分隔符,于是加上:string policyRequestString = "\0";    程序立马就能顺利通讯了。

      原来,在 Flex 程序发出 Socket 或 XmlSocket( 以下统称为 Socket) 请求前, FlashPlayer 会先判断是否为本地调用,如果不是。即用一个 Socket 去链接到你的服务端,三次握手成功后一方面发出字符串“ \0 “另一方面监听返回的安全策略。安全策略接收成功后, FlashPlayer 就断开验证的 Socket ,然后再运行程序本身的 Socket 。这里必须要使用分隔符“\0”,否则Flex会认为你没有发送安全策略,会自动放弃你的链接。

你可能感兴趣的:(Socket,通讯,C#.NET)