稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service)

稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service),第1张

概述[索引页] [源码下载] 稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service) 作者: webabcd 介绍 Silverlight 2.0 调用 WCF 的双向通信服务(Duplex Service) 。开发一个服务端主动向客服端发送股票信息的程序,首先客户端先向服务端发送需要监控的股票的股票代码,然后服务端在该股信息发生变化的时候将信息推 [索引页]
[源码下载]


稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service)

作者: webabcd


介绍
Silverlight 2.0 调用 WCF 的双向通信服务(Duplex Service) 。开发一个服务端主动向客服端发送股票信息的程序,首先客户端先向服务端发送需要监控的股票的股票代码,然后服务端在该股信息发生变化的时候将信息推送到客户端。
    服务端:
        定义服务契约及回调接口
        从当前上下文获取回调的客户端信道
        需要的话则向客户端信道“推”消息
    客户端:
        构造 PollingDuplexhttpBinding 并在其上创建 IDuplexSessionChannel 的信道工厂
        异步方式打开信道工厂
        异步方式打开信道
        构造需要发送到服务端的消息 System.ServiceModel.Channels.Message
        异步向服务端发送消息
        监听指定信道,用于异步方式接收服务端返回的消息
        不需要再接收服务端的消息则关闭信道


在线DEMO
http://www.cnblogs.com/webabcd/archive/2008/10/09/1307486.html


示例
服务端:
IDuplexService.cs

using  System;

using  System.Collections.Generic;

using  System.linq;

using  System.Runtime.Serialization;

using  System.ServiceModel;

using  System.Text;


using  System.ServiceModel.Channels;


/**/ /// <summary>

/// IDuplexService - 双工(Duplex)服务契约

/// CallbackContract - 双工(Duplex)服务的回调类型

/// </summary>

[ServiceContract(namespace  =   " Silverlight20 " , CallbackContract  =   typeof (IDuplexClIEnt))]

public   interface  IDuplexService

{

    
/**//// <summary>

    
/// 客户端向服务端发送消息的方法

    
/// </summary>

    
/// <param name="receivedMessage">客户端向服务端发送的消息 System.ServiceModel.Channels.Message</param>

    [OperationContract(IsOneWay = true)]

    
voID SendStockCode(Message receivedMessage);

}


/**/ /// <summary>

/// 双工(Duplex)服务的回调接口

/// </summary>

public   interface  IDuplexClIEnt

{

    
/**//// <summary>

    
/// 客户端接收服务端发送过来的消息的方法

    
/// </summary>

    
/// <param name="returnMessage">服务端向客户端发送的消息 System.ServiceModel.Channels.Message</param>

    [OperationContract(IsOneWay = true)]

    
voID ReceiveStockMessage(Message returnMessage);

}


DuplexService.cs

using  System;

using  System.Collections.Generic;

using  System.linq;

using  System.Runtime.Serialization;

using  System.ServiceModel;

using  System.Text;


using  System.ServiceModel.Channels;

using  System.Threading;

using  System.ServiceModel.Activation;

using  System.IO;


/**/ /// <summary>

/// Duplex 服务的服务端的实现

/// 本文以客户端向服务端提交股票代码,服务端定时向客户端发送股票信息为例

/// </summary>

public   class  DuplexService : IDuplexService

{

    IDuplexClIEnt _clIEnt;

    
bool _status = true;


    
/**//// <summary>

    
/// 客户端向服务端发送股票代码的方法

    
/// </summary>

    
/// <param name="receivedMessage">包含股票代码的 System.ServiceModel.Channels.Message </param>

    public voID SendStockCode(Message receivedMessage)

    

{

        
// 获取当前上下文的回调信道

        _clIEnt = OperationContext.Current.GetCallbackChannel<IDuplexClIEnt>();


        
// 如果发生错误则不再执行

        OperationContext.Current.Channel.Faulted += new EventHandler(delegate 

{ _status = false; });


        
// 获取用户提交的股票代码

        string stockCode = receivedMessage.Getbody<string>();


        
// 每3秒向客户端发送一次股票信息

        while (_status)

        

{

            
// 构造需要发送到客户端的 System.ServiceModel.Channels.Message

            
// Duplex 服务仅支持 Soap11 , Action 为请求的目的地(需要执行的某行为的路径)

            Message stockMessage = Message.CreateMessage(

                MessageVersion.soap11,

                
"Silverlight20/IDuplexService/ReceiveStockMessage",

                
string.Format("StockCode: {0}; StockPrice: {1}; CurrentTime: {2}",

                    stockCode,

                    
new Random().Next(1200),

                    DateTime.Now.ToString()));


            
try

            

{

                
// 向客户端“推”数据

                _clIEnt.ReceiveStockMessage(stockMessage);

            }

            
catch (Exception ex)

            

{

                
// 出错则记日志

                using (StreamWriter sw = new StreamWriter(@"C:/Silverlight_Duplex_Log.txt"true))

                

{

                    sw.Write(ex.ToString());

                    sw.Writeline();

                }

            }


            System.Threading.Thread.Sleep(
3000);

        }

    }

}

PollingDuplexServiceHostFactory.cs

using  System;

using  System.Collections.Generic;

using  System.linq;

using  System.Web;


using  System.ServiceModel;

using  System.ServiceModel.Channels;

using  System.ServiceModel.Activation;


/**/ /* 以下部分摘自文档 */


//  服务 svc 文件的 Factory 要指定为此类

public   class  PollingDuplexServiceHostFactory : ServiceHostFactoryBase

{

    
public overrIDe ServiceHostBase CreateServiceHost(string constructorString,

        Uri[] baseAddresses)

    

{

        
return new PollingDuplexSimplexServiceHost(baseAddresses);

    }

}


class  PollingDuplexSimplexServiceHost : ServiceHost

{

    
public PollingDuplexSimplexServiceHost(params System.Uri[] addresses)

    

{

        
base.InitializeDescription(typeof(DuplexService), new UriSchemeKeyedCollection(addresses));

    }


    
protected overrIDe voID InitializeRuntime()

    

{

        
// 配置 WCF 服务与 Silverlight 客户端之间的 Duplex 通信

        
// Silverlight 客户端定期轮询网络层上的服务,并检查回调信道上由服务端发送的所有新的消息

        
// 该服务会将回调信道上的由服务端发送的所有消息进行排队,并在客户端轮询服务时将这些消息传递到该客户端


        PollingDuplexBindingElement pdbe 
= new PollingDuplexBindingElement()

        
@H_419_1495@

{

            
// ServerPollTimeout - 轮询超时时间

            
// InactivityTimeout - 服务端与客户端在此超时时间内无任何消息交换的情况下,服务会关闭其会话


            ServerPollTimeout 
= TimeSpan.FromSeconds(3),

            InactivityTimeout 
= TimeSpan.FromMinutes(1)

        }
;


        
// 为服务契约(service contract)添加一个终结点(endpoint)

        
// Duplex 服务仅支持 Soap11

        this.AddServiceEndpoint(

            
typeof(IDuplexService),

            
new CustomBinding(

                pdbe,

                
new TextMessageEnCodingBindingElement(

                    MessageVersion.soap11,

                    System.Text.EnCoding.UTF8),

                
new httpTransportBindingElement()),

                
"");


        
base.InitializeRuntime();

    }

}


DuplexService.svc

<%

@ ServiceHost Language="C#" DeBUG="true" Service="DuplexService" CodeBehind="~/App_Code/DuplexService.cs" Factory="PollingDuplexServiceHostFactory"  %>

客户端:
DuplexService.xaml

< UserControl  x:Class ="Silverlight20.Communication.DuplexService"

    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  

    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" >

    
< StackPanel  HorizontalAlignment ="left"  margin ="5" >

    

        
< TextBox  x:name ="txtStockCode"  Text ="请输入股票代码"  margin ="5"   />

        
< button  x:name ="btnsubmit"  Content ="获取股票信息"  Click ="btnsubmit_Click"  margin ="5"   />

        
< button  x:name ="btnStop"  Content ="停止获取"  Click ="btnStop_Click"   margin ="5"   />

        
< TextBlock  x:name ="lblStockMessage"  margin ="5"   />

    

    
</ StackPanel >

</ UserControl >


DuplexService.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.ServiceModel;

using  System.ServiceModel.Channels;

using  System.Threading;

using  System.IO;


namespace  Silverlight20.Communication

{

    
public partial class DuplexService : UserControl

    

{

        SynchronizationContext _syncContext;


        
// 是否接收服务端发送过来的消息

        bool _status = true;


        
public DuplexService()

        

{

            InitializeComponent();

        }


        
private voID btnsubmit_Click(object sender, RoutedEventArgs e)

        

{

            _status 
= true;


            
// UI 线程

            _syncContext = SynchronizationContext.Current;


            PollingDuplexhttpBinding binding 
= new PollingDuplexhttpBinding()

            

{

                
// InactivityTimeout - 服务端与客户端在此超时时间内无任何消息交换的情况下,服务会关闭其会话

                InactivityTimeout = TimeSpan.FromMinutes(1)

            }
;


            
// 构造 IDuplexSessionChannel 的信道工厂

            IChannelFactory<IDuplexSessionChannel> factory =

                binding.BuildChannelFactory
<IDuplexSessionChannel>(new BindingParameterCollection());


            
// 打开信道工厂

            IAsyncResult factoryOpenResult =

                factory.Beginopen(
new AsyncCallback(OnopenCompleteFactory), factory);


            
if (factoryOpenResult.CompletedSynchronously)

            

{

                
// 如果信道工厂被打开的这个 异步 *** 作 已经被 同步完成 则执行下一步

                CompleteOpenFactory(factoryOpenResult);

            }

        }


        
private voID btnStop_Click(object sender, RoutedEventArgs e)

@H_419_2511@

        

{

            _status 
= false;

        }


        
voID OnopenCompleteFactory(IAsyncResult result)

        

{

            
// 该异步 *** 作已被同步完成的话则不做任何 *** 作,反之则执行下一步

            if (result.CompletedSynchronously)

                
return;

            
else

                CompleteOpenFactory(result);

        }


        
voID CompleteOpenFactory(IAsyncResult result)

        

{

            IChannelFactory
<IDuplexSessionChannel> factory = result.AsyncState as IChannelFactory<IDuplexSessionChannel>;


            
// 完成异步 *** 作,以打开信道工厂

            factory.EndOpen(result);


            
// 在信道工厂上根据指定的地址创建信道

            IDuplexSessionChannel channel =

                factory.CreateChannel(
new EndpointAddress("http://localhost:3036/DuplexService.svc"));


            
// 打开信道

            IAsyncResult channelOpenResult =

                channel.Beginopen(
new AsyncCallback(OnopenCompleteChannel), channel);


            
if (channelOpenResult.CompletedSynchronously)

            

{

                
// 如果信道被打开的这个 异步 *** 作 已经被 同步完成 则执行下一步

                CompleteOpenChannel(channelOpenResult);

            }

        }


        
voID OnopenCompleteChannel(IAsyncResult result)

        

{

            
// 该异步 *** 作已被同步完成的话则不做任何 *** 作,反之则执行下一步

            if (result.CompletedSynchronously)

                
return;

            
else

                CompleteOpenChannel(result);

        }


        
voID CompleteOpenChannel(IAsyncResult result)

        

{

            IDuplexSessionChannel channel 
= result.AsyncState as IDuplexSessionChannel;


            
// 完成异步 *** 作,以打开信道

            channel.EndOpen(result);


            
// 构造需要发送到服务端的 System.ServiceModel.Channels.Message (客户端终结点与服务端终结点之间的通信单元)

            Message message = Message.CreateMessage(

                channel.GetProperty
<MessageVersion>(), // MessageVersion.soap11 (Duplex 服务仅支持 Soap11)

                "Silverlight20/IDuplexService/SendStockCode"// Action 为请求的目的地(需要执行的某行为的路径)

                txtStockCode.Text);


            
// 向目的地发送消息

            IAsyncResult resultChannel =

                channel.BeginSend(message, 
new AsyncCallback(OnSend), channel);


            
if (resultChannel.CompletedSynchronously)

            

{

                
// 如果向目的地发送消息的这个 异步 *** 作 已经被 同步完成 则执行下一步

                CompleteOnSend(resultChannel);

            }


            
// 监听指定的信道,用于接收返回的消息

            ReceiveLoop(channel);

        }


        
voID OnSend(IAsyncResult result)

        

{

            
// 该异步 *** 作已被同步完成的话则不做任何 *** 作,反之则执行下一步

            if (result.CompletedSynchronously)

                
return;

            
else

                CompleteOnSend(result);

        }


        
voID CompleteOnSend(IAsyncResult result)

        

{

            
try

            

{

                IDuplexSessionChannel channel 
= (IDuplexSessionChannel)result.AsyncState;


                
// 完成异步 *** 作,以完成向目的地发送消息的 *** 作

                channel.EndSend(result);

            }

            
catch (Exception ex)

            

{

                _syncContext.Post(WriteText, ex.ToString() 
+ Environment.Newline);

            }

        }


        
voID ReceiveLoop(IDuplexSessionChannel channel)

        

{

            
// 监听指定的信道,用于接收返回的消息

            IAsyncResult result = 

                channel.BeginReceive(
new AsyncCallback(OnReceiveComplete), channel);


            
if (result.CompletedSynchronously)

@H_61_3404@

            

{

                CompleteReceive(result);

            }

        }


        
voID OnReceiveComplete(IAsyncResult result)

        

{

            
if (result.CompletedSynchronously)

                
return;

            
else

                CompleteReceive(result);

        }


        
voID CompleteReceive(IAsyncResult result)

        

{

            IDuplexSessionChannel channel 
= (IDuplexSessionChannel)result.AsyncState;


            
try

            

{

                
// 完成异步 *** 作,以接收到服务端发过来的消息

                Message receivedMessage = channel.EndReceive(result);


                
if (receivedMessage == null)

                

{

                    
// 服务端会话已被关闭

                    
// 此时应该关闭客户端会话,或向服务端发送消息以启动一个新的会话

                }

                
else

                

{

                    
// 将接收到的信息输出到界面上

                    string text = receivedMessage.Getbody<string>();

                    _syncContext.Post(WriteText, text 
+ Environment.Newline);


                    
if (!_status)

                    

{

                        
// 关闭信道

                        IAsyncResult resultFactory =

                            channel.BeginClose(
new AsyncCallback(OnCloseChannel), channel);


                        
if (resultFactory.CompletedSynchronously)

                        

{

                            CompleteCloseChannel(result);

                        }


                    }

                    
else

                    

{

                        
// 继续监听指定的信道,用于接收返回的消息

                        ReceiveLoop(channel);

                    }

                }

            }

            
catch (Exception ex)

            

{

                
// 出错则记日志

                using (StreamWriter sw = new StreamWriter(@"C:/Silverlight_Duplex_Log.txt"true))

                

{

                    sw.Write(ex.ToString());

                    sw.Writeline();

                }

            }

        }


        
voID OnCloseChannel(IAsyncResult result)

        

{

            
if (result.CompletedSynchronously)

                
return;

            
else

                CompleteCloseChannel(result);

        }


        
voID CompleteCloseChannel(IAsyncResult result)

        

{

            IDuplexSessionChannel channel 
= (IDuplexSessionChannel)result.AsyncState;


            
// 完成异步 *** 作,以关闭信道

            channel.EndClose(result);

        }


        
voID WriteText(object text)

        

{

            
// 将信息打到界面上

            lblStockMessage.Text += (string)text;

        }

    }

}


OK
[源码下载] 总结

以上是内存溢出为你收集整理的稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service)全部内容,希望文章能够帮你解决稳扎稳打Silverlight(23) - 2.0通信之调用WCF的双向通信(Duplex Service)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1052377.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存