天天看点

Silverlight实用窍门系列:67.Silverlight下的Socket通讯

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

<div class="cnblogs_code">

<pre><?xml version=<span style="color: #800000;">"</span><span style="color: #800000;">1.0</span><span style="color: #800000;">"</span> encoding=<span style="color: #800000;">"</span><span style="color: #800000;">utf-8</span><span style="color: #800000;">"</span> ?>

<access-policy>

  <cross-domain-access>

    <policy>

      <allow-<span style="color: #0000ff;">from</span>>

        <domain uri=<span style="color: #800000;">"</span><span style="color: #800000;">*</span><span style="color: #800000;">"</span>/>

      </allow-<span style="color: #0000ff;">from</span>>

      <grant-to>

        <socket-resource port=<span style="color: #800000;">"</span><span style="color: #800000;">4502-4534</span><span style="color: #800000;">"</span> protocol=<span style="color: #800000;">"</span><span style="color: #800000;">tcp</span><span style="color: #800000;">"</span>/>

      </grant-to>

    </policy>

  </cross-domain-access>

</access-policy></pre>

</div>

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

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

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

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

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

<p>  代码如下:</p>

<pre>    <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program

    {

        </span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)

        {

            </span><span style="color: #008000;">//</span><span style="color: #008000;">策略步骤一:启动监听943端口是否有需要安全策略文件请求</span>

            Thread access = <span style="color: #0000ff;">new</span> Thread(<span style="color: #0000ff;">new</span><span style="color: #000000;"> ThreadStart(accessThread));

            access.Start();

            </span><span style="color: #008000;">//</span><span style="color: #008000;">服务步骤一:启动服务器端,监听4525端口,是否有Socket对话请求</span>

            Thread server = <span style="color: #0000ff;">new</span> Thread(<span style="color: #0000ff;">new</span><span style="color: #000000;"> ThreadStart(ServerThread));

            server.Start();

        }

        </span><span style="color: #008000;">//</span><span style="color: #008000;">策略请求监听</span>

        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> accessThread()

            </span><span style="color: #008000;">//</span><span style="color: #008000;">获取943端口监听的Socket服务端</span>

            Socket socket = GetSocketServer(<span style="color: #800080;">943</span><span style="color: #000000;">);

            </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</span><span style="color: #000000;">)

            {

                Socket new_access </span>=<span style="color: #000000;"> socket.Accept();

                </span><span style="color: #0000ff;">string</span> clientPolicyString = <span style="color: #800000;">"</span><span style="color: #800000;"><policy-file-request/></span><span style="color: #800000;">"</span><span style="color: #000000;">;

                </span><span style="color: #0000ff;">byte</span>[] requestbytes = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[clientPolicyString.Length];

                new_access.Receive(requestbytes);

                </span><span style="color: #0000ff;">string</span> requeststring = System.Text.Encoding.UTF8.GetString(requestbytes, <span style="color: #800080;">0</span><span style="color: #000000;">, requestbytes.Length);

                </span><span style="color: #0000ff;">if</span> (requeststring ==<span style="color: #000000;"> clientPolicyString)

                {

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

                    <span style="color: #0000ff;">byte</span>[] accessbytes =<span style="color: #000000;"> GetPolicyToClient();

                    new_access.Send(accessbytes, accessbytes.Length, SocketFlags.None);

                    new_access.Close();

                }

                Thread.Sleep(</span><span style="color: #800080;">100</span><span style="color: #000000;">);

            }

        </span><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ServerThread()

            </span><span style="color: #008000;">//</span><span style="color: #008000;">获取4525端口监听的Socket服务端</span>

            Socket socket = GetSocketServer(<span style="color: #800080;">4525</span><span style="color: #000000;">);

                Socket _socket </span>=<span style="color: #000000;"> socket.Accept();

                </span><span style="color: #008000;">//</span><span style="color: #008000;">服务步骤二:如果有客户端请求的连接,则发送消息告知客户端</span>

                <span style="color: #0000ff;">byte</span>[] b2 = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span>[<span style="color: #800080;">1024</span><span style="color: #000000;">];

                _socket.Receive(b2);

                Console.WriteLine(Encoding.UTF8.GetString(b2).Replace(</span><span style="color: #800000;">"</span><span style="color: #800000;">\0</span><span style="color: #800000;">"</span>, <span style="color: #800000;">""</span><span style="color: #000000;">));

                </span><span style="color: #0000ff;">string</span> recString = <span style="color: #800000;">"</span><span style="color: #800000;">我已经收到消息了</span><span style="color: #800000;">"</span><span style="color: #000000;">;

                _socket.Send(Encoding.UTF8.GetBytes(recString));

                _socket.Close();

        </span><span style="color: #008000;">//</span><span style="color: #008000;">根据端口建立Socket服务器端</span>

        <span style="color: #0000ff;">static</span> Socket GetSocketServer(<span style="color: #0000ff;">int</span><span style="color: #000000;"> serverPort)

            Socket socket </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            socket.Bind(</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> IPEndPoint(IPAddress.Any, serverPort));

            socket.Listen(</span><span style="color: #800080;">40</span><span style="color: #000000;">);

            </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> socket;

        </span><span style="color: #008000;">//</span><span style="color: #008000;">获取安全策略文件的byte[]</span>

        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[] GetPolicyToClient()

            </span><span style="color: #0000ff;">string</span> path = Environment.CurrentDirectory.Replace(<span style="color: #800000;">"</span><span style="color: #800000;">\\bin\\Debug</span><span style="color: #800000;">"</span>,<span style="color: #800000;">""</span><span style="color: #000000;">);

            FileStream fs </span>= <span style="color: #0000ff;">new</span> FileStream(path+ <span style="color: #800000;">@"</span><span style="color: #800000;">\clientaccesspolicy.xml</span><span style="color: #800000;">"</span><span style="color: #000000;">, FileMode.Open);

            </span><span style="color: #0000ff;">int</span> length = (<span style="color: #0000ff;">int</span><span style="color: #000000;">)fs.Length;

            </span><span style="color: #0000ff;">byte</span>[] bytes = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[length];

            fs.Read(bytes, </span><span style="color: #800080;">0</span><span style="color: #000000;">, length);

            fs.Close();

            </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> bytes;

    }</span></pre>

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

<p>  <strong>客户端步骤一</strong>:发起服务器连接请求。</p>

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

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

<p>  <strong>客户端步骤四</strong>:获取到服务器返回的消息,关闭Socket </p>

<p>  客户端cs代码如下:</p>

<pre>    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> MainPage : UserControl

        </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> MainPage()

            InitializeComponent();

        System.Net.Sockets.Socket socket;

        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> button1_Click(<span style="color: #0000ff;">object</span><span style="color: #000000;"> sender, RoutedEventArgs e)

            </span><span style="color: #0000ff;">byte</span>[] userbytes = Encoding.UTF8.GetBytes(<span style="color: #0000ff;">this</span><span style="color: #000000;">.tbInput.Text);

            socket </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            SocketAsyncEventArgs socketArgs </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> SocketAsyncEventArgs();

            socketArgs.RemoteEndPoint </span>= <span style="color: #0000ff;">new</span> DnsEndPoint(<span style="color: #800000;">"</span><span style="color: #800000;">127.0.0.1</span><span style="color: #800000;">"</span>, <span style="color: #800080;">4525</span><span style="color: #000000;">);

            </span><span style="color: #008000;">//</span><span style="color: #008000;">将需要发送的内容转为byte[],保存到UserToken属性中</span>

            socketArgs.UserToken =<span style="color: #000000;"> userbytes;

            socketArgs.Completed </span>+= <span style="color: #0000ff;">new</span> EventHandler<SocketAsyncEventArgs><span style="color: #000000;">(socketArgs_Completed);

            </span><span style="color: #008000;">//</span><span style="color: #008000;">客户端步骤一:发起服务器连接请求。</span>

<span style="color: #000000;">            socket.ConnectAsync(socketArgs);

        </span><span style="color: #008000;">//</span><span style="color: #008000;">每发生一个Socket操作都讲激活此方法,操作包括(Connect/Send/Receive/None)</span>

        <span style="color: #0000ff;">void</span> socketArgs_Completed(<span style="color: #0000ff;">object</span><span style="color: #000000;"> sender, SocketAsyncEventArgs e)

            </span><span style="color: #0000ff;">if</span> (e.LastOperation ==<span style="color: #000000;"> SocketAsyncOperation.Connect)

                </span><span style="color: #008000;">//</span><span style="color: #008000;">客户端步骤二:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求</span>

                <span style="color: #0000ff;">byte</span>[] userbytes = (<span style="color: #0000ff;">byte</span><span style="color: #000000;">[])e.UserToken;

                e.SetBuffer(userbytes, </span><span style="color: #800080;">0</span><span style="color: #000000;">, userbytes.Length);

                socket.SendAsync(e);

            </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (e.LastOperation ==<span style="color: #000000;"> SocketAsyncOperation.Send)

                </span><span style="color: #008000;">//</span><span style="color: #008000;">客户端步骤三:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息</span>

                <span style="color: #0000ff;">byte</span>[] userbytes = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">byte</span>[<span style="color: #800080;">1024</span><span style="color: #000000;">];

                socket.ReceiveAsync(e);

            </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (e.LastOperation ==<span style="color: #000000;"> SocketAsyncOperation.Receive)

                </span><span style="color: #008000;">//</span><span style="color: #008000;">客户端步骤四:获取到服务器返回的消息,关闭Socket</span>

                <span style="color: #0000ff;">string</span> RecevieStr = Encoding.UTF8.GetString(e.Buffer, <span style="color: #800080;">0</span>, e.Buffer.Length).Replace(<span style="color: #800000;">"</span><span style="color: #800000;">\0</span><span style="color: #800000;">"</span>, <span style="color: #800000;">""</span><span style="color: #000000;">);

                </span><span style="color: #008000;">//</span><span style="color: #008000;">因为是异步Socket请求,所以需要使用UI线程更新lbShowMessage的显示效果</span>

                <span style="color: #0000ff;">this</span>.lbShowMessage.Dispatcher.BeginInvoke(<span style="color: #0000ff;">new</span><span style="color: #000000;"> DoThingDele(DoThing), RecevieStr);

                socket.Close();

        </span><span style="color: #008000;">//</span><span style="color: #008000;">更新UI</span>

        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> DoThing(<span style="color: #0000ff;">string</span><span style="color: #000000;"> arg)

            </span><span style="color: #0000ff;">this</span>.lbShowMessage.Content = <span style="color: #0000ff;">this</span>.lbShowMessage.Content + <span style="color: #800000;">"</span><span style="color: #800000;">-></span><span style="color: #800000;">"</span> +<span style="color: #000000;"> arg;

        </span><span style="color: #008000;">//</span><span style="color: #008000;">声明的一个DoThing方法委托</span>

        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">delegate</span> <span style="color: #0000ff;">void</span> DoThingDele(<span style="color: #0000ff;">string</span><span style="color: #000000;"> arg);

<p>  客户端Xaml前台代码如下:</p>

<pre>    <Grid x:Name=<span style="color: #800000;">"</span><span style="color: #800000;">LayoutRoot</span><span style="color: #800000;">"</span> Background=<span style="color: #800000;">"</span><span style="color: #800000;">White</span><span style="color: #800000;">"</span> ShowGridLines=<span style="color: #800000;">"</span><span style="color: #800000;">True</span><span style="color: #800000;">"</span>>

        <TextBox Height=<span style="color: #800000;">"</span><span style="color: #800000;">23</span><span style="color: #800000;">"</span> HorizontalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span> Margin=<span style="color: #800000;">"</span><span style="color: #800000;">20,20,0,0</span><span style="color: #800000;">"</span><span style="color: #000000;"> 

                 Name</span>=<span style="color: #800000;">"</span><span style="color: #800000;">tbInput</span><span style="color: #800000;">"</span> VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Top</span><span style="color: #800000;">"</span> Width=<span style="color: #800000;">"</span><span style="color: #800000;">243</span><span style="color: #800000;">"</span> />

        <Button Content=<span style="color: #800000;">"</span><span style="color: #800000;">发 送</span><span style="color: #800000;">"</span> Height=<span style="color: #800000;">"</span><span style="color: #800000;">23</span><span style="color: #800000;">"</span> HorizontalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span><span style="color: #000000;"> 

                Margin</span>=<span style="color: #800000;">"</span><span style="color: #800000;">279,20,0,0</span><span style="color: #800000;">"</span> Name=<span style="color: #800000;">"</span><span style="color: #800000;">button1</span><span style="color: #800000;">"</span> VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Top</span><span style="color: #800000;">"</span><span style="color: #000000;"> 

                Width</span>=<span style="color: #800000;">"</span><span style="color: #800000;">75</span><span style="color: #800000;">"</span> Click=<span style="color: #800000;">"</span><span style="color: #800000;">button1_Click</span><span style="color: #800000;">"</span> />

        <sdk:Label Height=<span style="color: #800000;">"</span><span style="color: #800000;">28</span><span style="color: #800000;">"</span> HorizontalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Left</span><span style="color: #800000;">"</span> Margin=<span style="color: #800000;">"</span><span style="color: #800000;">20,57,0,0</span><span style="color: #800000;">"</span><span style="color: #000000;">

                   Name</span>=<span style="color: #800000;">"</span><span style="color: #800000;">lbShowMessage</span><span style="color: #800000;">"</span> VerticalAlignment=<span style="color: #800000;">"</span><span style="color: #800000;">Top</span><span style="color: #800000;">"</span> Width=<span style="color: #800000;">"</span><span style="color: #800000;">358</span><span style="color: #800000;">"</span> />

    </Grid></pre>

<p> </p>

本文转自程兴亮 51CTO博客,原文链接:http://blog.51cto.com/chengxingliang/875576