[源码下载]
稳扎稳打Silverlight(53) - 4.0通信之对WCF NetTcpBinding的支持, 在Socket通信中通过HTTP检索策略文件, HTTP请求中的ClientHttp和BrowserHttp
作者: webabcd
介绍
Silverlight 4.0 通信方面的增强:
- NetTcpBinding - 通过 NetTcpBinding 与 WCF 服务进行通信
- 支持在 Socket 通信中通过 HTTP 的方式检索策略文件
- HTTP 请求中的 ClientHttp 方式和 BrowserHttp 方式的应用
在线DEMO
http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html
示例
1、演示如何通过 NetTcpBinding 与 WCF 进行双向通信
服务端:
IDuplex.cs
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace SocketServer
{
[ServiceContract(CallbackContract = typeof (IDuplexCallback))]
public interface IDuplex
{
[OperationContract(IsOneWay = true )]
void HelloDuplex( string msg);
}
public interface IDuplexCallback
{
[OperationContract(IsOneWay = true )]
void HelloDuplexCallback( string msg);
}
}
Duplex.cs
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace SocketServer
{
public class Duplex : IDuplex
{
private IDuplexCallback _callback;
// 服务端方法,其用于被客户端调用
public void HelloDuplex( string msg)
{
Program.Form1.ShowMessage(msg);
if (_callback == null )
{
// 实例化回调接口
_callback = OperationContext.Current.GetCallbackChannel < IDuplexCallback > ();
// 每一秒调用一次回调接口(即调用客户端的方法)
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 3000d;
timer.Elapsed += delegate { _callback.HelloDuplexCallback( " 服务端发给客户端的信息: " + DateTime.Now.ToString( " yyyy-MM-dd HH:mm:ss " )); };
timer.Start();
}
}
}
}
App.config
代码 <? xml version="1.0" encoding="utf-8" ?>
< configuration >
< system.serviceModel >
< services >
<!--
元数据地址:http://localhost:12345/SocketServer/Duplex/mex
TCP 地址:net.tcp://localhost:4502/SocketServer/Duplex
TCP 端口限制在 4502 - 4534 之间
-->
< service name ="SocketServer.Duplex" >
< endpoint address ="SocketServer/Duplex" binding ="customBinding" contract ="SocketServer.IDuplex" />
< endpoint address ="mex" binding ="mexHttpBinding" contract ="IMetadataExchange" />
< host >
< baseAddresses >
< add baseAddress ="http://localhost:12345/SocketServer/Duplex" />
< add baseAddress ="net.tcp://localhost:4502/" />
</ baseAddresses >
</ host >
</ service >
</ services >
<!--
Silverlight 4.0 对 NetTcpBinding 的支持是通过自定义绑定的方式来实现的。服务端和客户端都需要使用自定义绑定
-->
< bindings >
< customBinding >
< binding >
< binaryMessageEncoding ></ binaryMessageEncoding >
< tcpTransport maxReceivedMessageSize ="2147483647" maxBufferSize ="2147483647" />
</ binding >
</ customBinding >
</ bindings >
< behaviors >
< serviceBehaviors >
< behavior >
< serviceMetadata httpGetEnabled ="true" />
< serviceDebug includeExceptionDetailInFaults ="true" />
</ behavior >
</ serviceBehaviors >
</ behaviors >
</ system.serviceModel >
</ configuration >
Form1.cs 代码 // 启动 WCF 服务,用于演示 Silverlight 4.0 与 WCF 的交互(基于 NetTcpBinding 绑定)
private void LaunchNetTcpBinding()
{
ServiceHost host = new ServiceHost( typeof (SocketServer.Duplex));
host.Open();
ShowMessage( " 演示 NetTcpBinding 的 WCF 服务已启动 " );
}
客户端(需要引用服务的元数据):
NetTcpBinding.xaml 代码 < navigation:Page x:Class ="Silverlight40.Communication.NetTcpBinding"
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title ="NetTcpBinding Page" >
< Grid x:Name ="LayoutRoot" >
< StackPanel HorizontalAlignment ="Left" >
< Button Name ="btnSend" Content ="发送信息到服务端" Click ="btnSend_Click" />
< TextBlock Name ="lblMsg" />
</ StackPanel >
</ Grid >
</ navigation:Page >
NetTcpBinding.xaml.cs 代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.ServiceModel;
using System.Net.Sockets;
using System.ServiceModel.Channels;
namespace Silverlight40.Communication
{
public partial class NetTcpBinding : Page, DuplexServiceReference.IDuplexCallback
{
private DuplexServiceReference.DuplexClient _client;
public NetTcpBinding()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private void btnSend_Click( object sender, RoutedEventArgs e)
{
// 客户端与服务端之间如果没有信道的话,则产生这个信道
if (_client == null )
{
var ctx = new InstanceContext( this );
// 通过配置文件的方式建立信道
_client = new DuplexServiceReference.DuplexClient(ctx);
// 通过编写代码的方式建立信道
}
// 调用服务端的方法
_client.HelloDuplexAsync( " 客户端发给服务端的信息: " + DateTime.Now.ToString( " yyyy-MM-dd HH:mm:ss " ));
// _client.HelloDuplexCompleted - 在此 Handler 中获取服务端方法的返回值,因为本例是 IsOneWay 方式,所以没有返回值
}
// 客户端方法,其用于被服务端调用
public void HelloDuplexCallback( string msg)
{
lblMsg.Text += msg + " \n " ;
}
}
}
ServiceReferences.ClientConfig 代码 < configuration >
< system.serviceModel >
<!--
使用 NetTcpBinding 绑定需要先引用 System.ServiceModel.NetTcp.dll 程序集
-->
< client >
< endpoint address ="net.tcp://localhost:4502/SocketServer/Duplex" binding ="customBinding" contract ="DuplexServiceReference.IDuplex"
bindingConfiguration ="netTcpBinding" />
</ client >
<!--
Silverlight 4.0 对 NetTcpBinding 的支持是通过自定义绑定的方式来实现的。服务端和客户端都需要使用自定义绑定
-->
< bindings >
< customBinding >
< binding name ="netTcpBinding" >
< binaryMessageEncoding />
< tcpTransport maxReceivedMessageSize ="2147483647" maxBufferSize ="2147483647" />
</ binding >
</ customBinding >
</ bindings >
</ system.serviceModel >
</ configuration >
2、通过 HTTP 的方式检索 Socket 通信的安全策略
SocketClientRetrievePolicyFileViaHttp.xaml 代码 < navigation:Page x:Class ="Silverlight40.Communication.SocketClientRetrievePolicyFileViaHttp"
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc ="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title ="SocketCommunicationRetrievePolicyFileViaHttp Page" >
< Grid x:Name ="LayoutRoot" >
< TextBlock >
< Run > 以前的 Socket 通信,在连接之前先要以 943 端口的 TCP 方式在服务端检索策略文件 </ Run >
< LineBreak />
< Run > Silverlight 4.0 中的 Socket 通信可以通过 80 端口的 HTTP 方式检索策略文件,获取到的策略文件作用于此 HTTP 地址所解析出的 IP </ Run >
< LineBreak />
< Run > System.Net.Sockets.SocketAsyncEventArgs.SocketClientAccessPolicyProtocol - 指定 Socket 通信检索策略文件的方式 [System.Net.Sockets.SocketClientAccessPolicyProtocol 枚举] </ Run >
< LineBreak />
< Run > 可能的值有:System.Net.Sockets.SocketClientAccessPolicyProtocol.Http 和 System.Net.Sockets.SocketClientAccessPolicyProtocol.Tcp </ Run >
</ TextBlock >
</ Grid >
</ navigation:Page >
3、两种 HTTP 请求方式,即 ClientHttp 和 BrowserHttp 的区别
服务端:
HttpResult.aspx.cs 代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Silverlight40.Web
{
public partial class HttpResult : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e)
{
// 返回当前 HTTP 请求的 HTTP 方法及 Cookie
Response.Write( string .Format( " HttpMethod: {0}, Cookie - name: {1} " , Request.HttpMethod, Request.Cookies[ " name " ].Value));
Response.End();
}
}
}
客户端:
ClientHttpAndBrowserHttp.xaml.cs 代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.Net.Browser;
using System.IO;
using System.Threading;
namespace Silverlight40.Communication
{
public partial class ClientHttpAndBrowserHttp : Page
{
SynchronizationContext _syncContext;
public ClientHttpAndBrowserHttp()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
_syncContext = SynchronizationContext.Current;
// 创建一个 ClientHttp 方式的 HttpWebRequest 对象
HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create( new Uri( " http://localhost:9483/HttpResult.aspx " ));
// ClientHttp 可以使用任何 Http 方法(BrowserHttp 只能使用 GET 和 POST)
request.Method = " PUT " ;
// ClientHttp 可以手工构造 Cookie(如果需要 Forms 验证或 NTLM 验证则只能通过 BroswerHttp 方式)
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add( new Uri( " http://localhost:9483 " ), new Cookie( " name " , " webabcd " ));
request.BeginGetResponse( new AsyncCallback(ResponseCallback), request);
}
// 获取服务返回的结果
private void ResponseCallback(IAsyncResult result)
{
HttpWebRequest request = result.AsyncState as HttpWebRequest;
WebResponse response = request.EndGetResponse(result) as HttpWebResponse;
if (response != null )
{
Stream responseStream = response.GetResponseStream();
using (StreamReader sr = new StreamReader(responseStream))
{
string s = sr.ReadToEnd();
Deployment.Current.Dispatcher.BeginInvoke( delegate { MessageBox.Show(s); });
}
}
}
}
}
OK
[源码下载]