天天看點

穩紮穩打Silverlight(53) - 4.0通信之對WCF NetTcpBinding的支援, 在Socket通信中通過HTTP檢索政策檔案, HTTP請求中的ClientHttp和Browse

  [源碼下載下傳]

穩紮穩打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

[源碼下載下傳]