[源碼下載下傳]
穩紮穩打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
[源碼下載下傳]