天天看点

稳扎稳打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

[源码下载]