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

简介:

<p>  在Silverlight中进行通讯,只能使用4502-4534之间的端口进行数据传输,另外Silverlight客户端会自动向943端口的服务器端发送一个&ldquo;&lt;policy-file-request/&gt;&rdquo;的语句请求,然后服务器端943端口回发以下文件以许可Socket通讯。</p>
<div class="cnblogs_code">
<pre>&lt;?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> ?&gt;
&lt;access-policy&gt;
  &lt;cross-domain-access&gt;
    &lt;policy&gt;
      &lt;allow-<span style="color: #0000ff;">from</span>&gt;
        &lt;domain uri=<span style="color: #800000;">"</span><span style="color: #800000;">*</span><span style="color: #800000;">"</span>/&gt;
      &lt;/allow-<span style="color: #0000ff;">from</span>&gt;
      &lt;grant-to&gt;
        &lt;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>/&gt;
      &lt;/grant-to&gt;
    &lt;/policy&gt;
  &lt;/cross-domain-access&gt;
&lt;/access-policy&gt;</pre>
</div>
<p>  A.现在我们首先来看服务器端的代码,主要分为策略响应步骤和服务响应步骤。</p>
<p>  <strong>策略步骤一</strong>:启动监听943端口是否有需要安全策略文件请求</p>
<p>  <strong>策略步骤二</strong>:如果客户端请求是&lt;policy-file-request/&gt;,则将安全策略文件作为bytes发送给客户端</p>
<p>  <strong>服务步骤一</strong>:启动服务器端,监听4525端口,是否有Socket对话请求</p>
<p>  <strong>服务步骤二</strong>:如果有客户端请求的连接,则发送消息告知客户端</p>
<p>  代码如下:</p>
<div class="cnblogs_code">
<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;">&lt;policy-file-request/&gt;</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;">策略步骤二:如果客户端请求是&lt;policy-file-request/&gt;,则将安全策略文件作为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;">);
            </span><span style="color: #0000ff;">while</span> (<span style="color: #0000ff;">true</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();
                Thread.Sleep(</span><span style="color: #800080;">100</span><span style="color: #000000;">);
            }
        }
        </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>
</div>
<p>  B.其次我们来看客户端操作,分为以下几个步骤:</p>
<p>  <strong>客户端步骤一</strong>:发起服务器连接请求。</p>
<p>  <strong>客户端步骤二</strong>:连接服务器成功,将需要发送的数据放入缓冲区中,然后异步向服务器发送消息请求</p>
<p>  <strong>客户端步骤三</strong>:消息发送成功,此时设置一个新的缓冲区实例,并且发起异步接收服务器返回的消息</p>
<p>  <strong>客户端步骤四</strong>:获取到服务器返回的消息,关闭Socket </p>
<p>  客户端cs代码如下:</p>
<div class="cnblogs_code">
<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&lt;SocketAsyncEventArgs&gt;<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;">];
                e.SetBuffer(userbytes, </span><span style="color: #800080;">0</span><span style="color: #000000;">, userbytes.Length);
                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;">-&gt;</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);
    }</span></pre>
</div>
<p>  客户端Xaml前台代码如下:</p>
<div class="cnblogs_code">
<pre>    &lt;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>&gt;
        &lt;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> /&gt;
        &lt;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> /&gt;
        &lt;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> /&gt;
    &lt;/Grid&gt;</pre>
</div>
<p>  最后效果如下,如需源码请点击 <a href="http://files.cnblogs.com/chengxingliang/SLSocket.zip">SLSocket.zip</a> 下载,本文演示的是最简单通讯效果:</p>
<p><img src="http://pic002.cnblogs.com/images/2012/140041/2012052317265429.png" alt="" /></p>
<p>&nbsp;</p>
<p><img src="http://pic002.cnblogs.com/images/2012/140041/2012052317263654.png" alt="" /></p>



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


相关文章
|
安全 网络协议 网络安全
http https socket通讯详解?
http https socket通讯详解?
105 0
|
28天前
|
网络协议 机器人 C++
KUKA机器人Socket通讯配置方法:技术干货分享
【10月更文挑战第7天】在现代自动化生产线上,KUKA机器人凭借其高效、灵活和精确的特点,成为众多企业的首选。为了实现KUKA机器人与其他设备或系统之间的数据交互,Socket通讯配置显得尤为重要。本文将详细介绍KUKA机器人Socket通讯的配置方法,帮助大家在工作中更好地掌握这一技术。
149 2
|
5月前
|
缓存 网络协议 Linux
c++实战篇(三) ——对socket通讯服务端与客户端的封装
c++实战篇(三) ——对socket通讯服务端与客户端的封装
112 0
|
6月前
|
算法 Linux 调度
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
446 1
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(一)--实时端socket创建流程
|
5月前
|
Java
java使用ServerSocket和Socket实现客户端与服务端通讯
java使用ServerSocket和Socket实现客户端与服务端通讯
|
移动开发 监控 网络协议
基于Socket通讯(C#)和WebSocket协议(net)编写的两种聊天功能(文末附源码下载地址)
基于Socket通讯(C#)和WebSocket协议(net)编写的两种聊天功能(文末附源码下载地址)
|
JSON 缓存 JavaScript
Socket.IO服务端与客户端消息通讯
Socket.IO服务端与客户端消息通讯
285 0
|
Android开发
Android Socket通讯 之 心跳消息
Android Socket通讯 之 心跳消息
189 0
Android Socket通讯 之 心跳消息
|
设计模式 Java Android开发
Android Socket通讯 之 表情列表优化、业务逻辑优化
Android Socket通讯 之 表情列表优化、业务逻辑优化
232 0
Android Socket通讯 之 表情列表优化、业务逻辑优化
|
Android开发
Android Socket通讯 分离服务端和客户端、发送表情消息
Android Socket通讯 分离服务端和客户端、发送表情消息
134 0
Android Socket通讯 分离服务端和客户端、发送表情消息