微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Silverlight下的Socket通讯

本文版权归 博客园 程兴亮 所有,如有转载,请严格按如下方式表明原文作者及出处,以示尊重!!

作者:程兴亮
出处:http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html

 

  在Silverlight中进行通讯,只能使用4502-4534之间的端口进行数据传输,另外Silverlight客户端会自动向943端口的服务器端发送一个“<policy-file-request/>”的语句请求,然后服务器端943端口回发以下文件以许可Socket通讯。

<?xml version="1.0" encoding="utf-8" ?>
<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>

  A.现在我们首先来看服务器端的代码,主要分为策略响应步骤和服务响应步骤。

  策略步骤一:启动监听943端口是否有需要安全策略文件请求

  策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端

  服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求

  服务步骤二:如果有客户端请求的连接,则发送消息告知客户端

  代码如下:

    class Program
    {
        static void Main(string[] args)
        {
            //策略步骤一:启动监听943端口是否有需要安全策略文件请求
            Thread access = new Thread(new ThreadStart(accessthread));
            access.Start();

            //服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求
            Thread server = new Thread(new ThreadStart(ServerThread));
            server.Start();
        }
        //策略请求监听
        static void accessthread()
        {
            //获取943端口监听的Socket服务端
            Socket socket = GetSocketServer(943);
            while (true)
            {
                Socket new_access = socket.Accept();
                string clientPolicyString = "<policy-file-request/>";
                byte[] requestbytes = new byte[clientPolicyString.Length];
                new_access.Receive(requestbytes);
                string requeststring = System.Text.Encoding.UTF8.GetString(requestbytes,0,requestbytes.Length);

                if (requeststring == clientPolicyString)
                {
                    //策略步骤二:如果客户端请求是<policy-file-request/>,则将安全策略文件作为bytes发送给客户端
                    byte[] accessbytes = GetPolicyToClient();
                    new_access.Send(accessbytes,accessbytes.Length,SocketFlags.None);
                    new_access.Close();
                }
                Thread.Sleep(100);
            }
        }

        static void ServerThread()
        {
            //获取4525端口监听的Socket服务端
            Socket socket = GetSocketServer(4525);
            while (true)
            {
                Socket _socket = socket.Accept();
                //服务步骤二:如果有客户端请求的连接,则发送消息告知客户端
                byte[] b2 = new byte[1024];
                _socket.Receive(b2);
                Console.WriteLine(Encoding.UTF8.GetString(b2).Replace("\0",""));
                string recString = "我已经收到消息了";
                _socket.Send(Encoding.UTF8.GetBytes(recString));
                _socket.Close();
                Thread.Sleep(100);
            }
        }
        //根据端口建立Socket服务器端
        static Socket GetSocketServer(int serverPort)
        {
            Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            socket.Bind(new IPEndPoint(IPAddress.Any,serverPort));
            socket.Listen(40);
            return socket;
        }
        //获取安全策略文件的byte[]
        static byte[] GetPolicyToClient()
        {
            string path = Environment.CurrentDirectory.Replace("\\bin\\Debug","");
            FileStream fs = new FileStream(path+ @"\clientaccesspolicy.xml",FileMode.Open);
            int length = (int)fs.Length;
            byte[] bytes = new byte[length];
            fs.Read(bytes,0,length);
            fs.Close();
            return bytes;
        }

    }

  B.其次我们来看客户端操作,分为以下几个步骤:

  客户端步骤一:发起服务器连接请求。

  客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求

  客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息

  客户端步骤四获取到服务器返回的消息,关闭Socket 

  客户端cs代码如下:

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }
        System.Net.sockets.socket socket;

        private void button1_Click(object sender,RoutedEventArgs e)
        {
            byte[] userbytes = Encoding.UTF8.GetBytes(this.tbInput.Text);
            socket = new System.Net.sockets.socket(AddressFamily.InterNetwork,ProtocolType.Tcp);
            socketasynceventargs socketArgs = new socketasynceventargs();
            socketArgs.RemoteEndPoint = new DnsEndPoint("127.0.0.1",4525);
            //将需要发送的内容转为byte[],保存到UserToken属性
            socketArgs.UserToken = userbytes;
            socketArgs.Completed += new EventHandler<socketasynceventargs>(socketArgs_Completed);
            //客户端步骤一:发起服务器连接请求。
            socket.ConnectAsync(socketArgs);
        }
        //每发生一个Socket操作都讲激活此方法,操作包括(Connect/Send/Receive/None)
        void socketArgs_Completed(object sender,socketasynceventargs e)
        {
            if (e.LastOperation == SocketAsyncoperation.Connect)
            {
                //客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求
                byte[] userbytes = (byte[])e.UserToken;
                e.SetBuffer(userbytes,userbytes.Length);
                socket.SendAsync(e);
            }
            else if (e.LastOperation == SocketAsyncoperation.Send)
            {
                //客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息
                byte[] userbytes = new byte[1024];
                e.SetBuffer(userbytes,userbytes.Length);
                socket.ReceiveAsync(e);
            }
            else if (e.LastOperation == SocketAsyncoperation.Receive)
            {
                //客户端步骤四:获取到服务器返回的消息,关闭Socket
                string RecevieStr = Encoding.UTF8.GetString(e.Buffer,0,e.Buffer.Length).Replace("\0","");
                //因为是异步Socket请求,所以需要使用UI线程更新lbShowMessage的显示效果
                this.lbShowMessage.dispatcher.BeginInvoke(new DoThingDele(DoThing),RecevieStr);
                socket.Close();
            }
        }
        //更新UI
        public void DoThing(string arg)
        {
            this.lbShowMessage.Content = this.lbShowMessage.Content + "->" + arg;
        }
        //声明的一个DoThing方法委托
        public delegate void DoThingDele(string arg);
    }

  客户端Xaml前台代码如下:

    <Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True">
        <TextBox Height="23" HorizontalAlignment="Left" Margin="20,20,0" 
                 Name="tbInput" VerticalAlignment="Top" Width="243" />
        <Button Content="发 送" Height="23" HorizontalAlignment="Left" 
                Margin="279,0" Name="button1" VerticalAlignment="Top" 
                Width="75" Click="button1_Click" />
        <sdk:Label Height="28" HorizontalAlignment="Left" Margin="20,57,0"
                   Name="lbShowMessage" VerticalAlignment="Top" Width="358" />
    </Grid>

  最后效果如下,如需源码请点击 SLSocket.zip 下载,本文演示的是最简单通讯效果

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐