zoukankan      html  css  js  c++  java
  • Silverlight实用窍门系列:67.Silverlight下的Socket通讯

      在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, SocketType.Stream, 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, 0, userbytes.Length);
                    socket.SendAsync(e);
                }
                else if (e.LastOperation == SocketAsyncOperation.Send)
                {
                    //客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息
                    byte[] userbytes = new byte[1024];
                    e.SetBuffer(userbytes, 0, 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,0" 
                     Name="tbInput" VerticalAlignment="Top" Width="243" />
            <Button Content="发 送" Height="23" HorizontalAlignment="Left" 
                    Margin="279,20,0,0" Name="button1" VerticalAlignment="Top" 
                    Width="75" Click="button1_Click" />
            <sdk:Label Height="28" HorizontalAlignment="Left" Margin="20,57,0,0"
                       Name="lbShowMessage" VerticalAlignment="Top" Width="358" />
        </Grid>

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

  • 相关阅读:
    linux使用shell执行一个Python文件
    shell编程
    mysql之通过cmd连接远程数据库
    单词辨析
    安全测试
    Linux下使用crontab执行一个shell脚本
    重新梳理Linux系统中Python环境的问题
    selenium 定位元素不稳定怎么解决?
    爬虫数据分析的前景
    Linux下部署python selenium UI自动化测试
  • 原文地址:https://www.cnblogs.com/chengxingliang/p/2515100.html
Copyright © 2011-2022 走看看