<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>
<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;"><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;">);
</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<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;">];
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;">-></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> <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>
</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> </p>
<p><img src="http://pic002.cnblogs.com/images/2012/140041/2012052317263654.png" alt="" /></p>
本文转自程兴亮 51CTO博客,原文链接:http://blog.51cto.com/chengxingliang/875576