一起谈.NET技术,Siverlight与WCF通信之双工netTcp实现视频对话

  效果

  先看看效果再说,基本逻辑是两个人通过Silverlight端,借助TCP协议分别向服务器不断传输视频,服务器接收到视频后,会检测这些视频是发给谁的,然后回调某个客户端来接收并显示这些视频。

  实现

  双工的服务契约定义:


[ServiceContract(CallbackContract=typeof(IChatServiceCallBack))]
public interface IChatService
{
[OperationContract]
void SendVideo(UserVideo userVideo);
}
[ServiceContract]
public interface IChatServiceCallBack
{
[OperationContract(IsOneWay=true)]
void GetVideos(List<UserVideo> listVideos);
}

  数据契约,由三部分组成,发送者,接受者和视频流,方便服务器进行判断,选择接收的回调句柄。


[DataContract]
public class UserVideo
{
[DataMember]
public string UserName { get; set; }
[DataMember]
public string PartnerName { set; get; }
[DataMember]
public byte[] VideoByte { set; get; }
}

  既然是双工的,当然我们还需要定义一个客户端的回调句柄类,包括两个属性,一个是客户端名称,一个是回调句柄:


public class ClientHandler {

public string Name { set; get; }

public IChatServiceCallBack Client { set; get; } }

  服务实现,这里没有采用定时检测视频集合,而是在每次有客户端上传视频时进行检测并回调客户端来接收,这样做的好处是事件驱动,比定时检测更具有准确性。


public class ChatService : IChatService
{
static List<ClientHandler> listOfClientHandler = new List<ClientHandler>();
private static List<UserVideo> listVideos = new List<UserVideo>();
IChatServiceCallBack client;
public void SendVideo(UserVideo userVideo)
{
Console.WriteLine("receiving...");
listVideos.Add(userVideo);

client = OperationContext.Current.GetCallbackChannel<IChatServiceCallBack>();
if (listOfClientHandler.Where(m => m.Name == userVideo.UserName).Count() == 0)
{
listOfClientHandler.Add(new ClientHandler() { Name=userVideo.UserName, Client=client });
}

foreach(var item in listOfClientHandler)
{
if (listVideos.Where(m => m.PartnerName == item.Name).Count() > 0)
{
var videos = listVideos.Where(m => m.PartnerName == item.Name).ToList();
item.Client.GetVideos(videos);
Console.WriteLine("sending...");
listVideos.RemoveAll(m => m.PartnerName == item.Name);//处理一个视频后直接从服务器上删除此视频
}
}
}
}

  客户端,基本原理是先发送视频,然后定义回调函数来处理服务器的回调:


void btnSendVideo_Click(object sender, RoutedEventArgs e)
{
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
proxy = new ChatServiceClient();
proxy.GetVideosReceived += new EventHandler<GetVideosReceivedEventArgs>(proxy_GetVideosReceived);
WriteableBitmap bmp = new WriteableBitmap(this.rectangleUser, null);
MemoryStream ms = new MemoryStream();
EncodeJpeg(bmp, ms);
UserVideo userVideo = new UserVideo();
userVideo.PartnerName = this.Partner;
userVideo.UserName = this.User;
userVideo.VideoByte = ms.GetBuffer();
proxy.SendVideoCompleted += (se,ev) => { };
proxy.SendVideoAsync(userVideo);
}

void proxy_GetVideosReceived(object sender, GetVideosReceivedEventArgs e)
{
foreach (ChatService.UserVideo video in e.listVideos)
{
MemoryStream ms = new MemoryStream(video.VideoByte);
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(ms);
imagePartner.Source = bitmap;
ms.Close();
}
}

  app.config配置:


<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpBindConfig"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="00:10:00"
sendTimeout="00:01:00"
transactionFlow="false"
transferMode="Buffered"
transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard"
listenBacklog="10"
maxBufferPoolSize="2147483647 "
maxBufferSize="2147483647 "
maxConnections="10"
maxReceivedMessageSize="2147483647 ">
<readerQuotas maxDepth="32"
maxStringContentLength="2147483647 "
maxArrayLength="2147483647 "
maxBytesPerRead="4096"
maxNameTableCharCount="16384" />
<reliableSession ordered="true"
inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
</security>
</binding>
</netTcpBinding>
</bindings>
<services>

<service behaviorConfiguration="Server.ChatServiceBehavior" name="Server.ChatService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:4503/ChatService"/>
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" contract="Server.IChatService" bindingConfiguration="netTcpBindConfig"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" ></endpoint>
</service>

</services>
<behaviors>
<serviceBehaviors>
<behavior name="Server.ChatServiceBehavior">
<serviceMetadata/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

  遗留问题
  1、由于客户端是定时上传视频流,而非长连接方式,需要不停的调用服务器来上传视频,有些耗资源,并且有时会出现下面的异常,猜想是由于不停的连接导致。

  2、wcf传输方式配置的是transferMode="Buffered",这种方式并不适合流式传输。实时性上仍有待改进。

  源码下载:http://files.cnblogs.com/wengyuli/chatTCPduplex.rar

时间: 2024-09-23 19:47:21

一起谈.NET技术,Siverlight与WCF通信之双工netTcp实现视频对话的相关文章

Siverlight与WCF通信之双工netTcp实现视频对话

效果 先看看效果再说,基本逻辑是两个人通过Silverlight端,借助TCP协议分别向服务器不断传输视频,服务器接收到视频后,会检测这些视频是发给谁的,然后回调某个客户端来接收并显示这些视频. 实现 双工的服务契约定义: [ServiceContract(CallbackContract=typeof(IChatServiceCallBack))] public interface IChatService { [OperationContract] void SendVideo(UserVi

Silverlight与WCF之间的通信(7) 双工netTcp实现视频对话

效果 先看看效果再说,基本逻辑是两个人通过Silverlight端,借助TCP协议分别向服务器不断传输视频, 服务器接收到视频后,会检测这些视频是发给谁的,然后回调某个客户端来接收并显示这些视频. 实现 双工的服务契约定义 [ServiceContract(CallbackContract=typeof (IChatServiceCallBack))] public interface IChatService { [OperationContract] void SendVideo(UserV

一起谈.NET技术,使用WCF实现SOA面向服务编程——使用AJAX+WCF服务页面开发

在上一篇讲到,如果将BLL层的每一个类都转化为*.svc,这是一个不实在的想法.它会使服务变化复杂,难于管理. 这时候,我们第一时间想到的是23个简单开发模式中的Factory,在这里,Factory正好派上用场.我们把这个Factory称之为管道(pipeline) ,通过这个管道客户端可以随意调用服务器BLL层里面的类. (关于管道的概念,建议参考Cory Isaacson的杰作<多核应用架构关键技术-软件管道与soa>) 当你使用B/S方式开发UI层时,只要了解此开发模式,使用Ajax加

一起谈.NET技术,使用WCF实现SOA面向服务编程——简单的WCF开发实例

前面为大家介绍过WCF的特点,现在再讲解一下WCF基础概念. 在WCF里,各个Application之间的通信是由EndPoint来实现的,EndPoint是WCF实现通信的核心要素.一个WCF Service可由多个EndPoint集合组成,每个EndPoint只能有一种绑定,就是说EndPoint就是通信的入口,客户端和服务端通过 EndPoint交换信息. <service name = " " >< endpoint address = ""

一起谈.NET技术,Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放-结局(四十)

查看本系列其他相关文章请点击:Silverlight+WCF 新手实例象棋专题索引 在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 在Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放(三十九)中,我们实现了用户的棋谱回放,在文章的下面,我们曾留下了两个问题: 下棋者在下棋过程,要不要开放"回放"功能,如果开放,需要注意什么? 观众在回放过程中,突然又传来一个棋步,需要注意什么? 在解答这两个问题之前,我们先来解答上一篇的截图中发现的问题: 不知

一起谈.NET技术,当Silverlight同时遇上TCP和HTTP的WCF服务

如果只是单一的TCP通信 如果你的silverlight应用因为一些特殊原因跟WCF通信时使用的不是Http协议,而是TCP协议,并且是Host到控制台上的.那么假设是下面这个简单的服务: 1,WCF中的主机服务代码如下: class Program {static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(HelloService)); host.Open(); Console.WriteLine(

在Silverlight下使用WCF通信

关于在SL下实现WCF通信的文章很多,因此我着重从我的实践上讲解,这样可 能易懂一些. 一.简单介绍下WCF 全名:Windows Communication Foundation 从Dotnet Framework 3.0开始出 现,WCF通信提供了用HTTP.TCP和IPC信道进行通信的多个方法.WCF提供的信道 使用DCOM进行通信.WCF适合于要独立于平台快速的发送消息.服务提供一个端 点,包括三个:合同Contract.绑定Binding和地址Endpoint.合同定义了服务 提供的操

《创业家》牛文文:少谈点模式多谈点技术

"模式"如同当年的"主义",流行于各种创业大赛.创业励志节目.论坛的"街头"式秀场 文/创业家 牛文文 "美国某某公司你知道吧?就是刚被戴尔.惠普.思科十几亿美元抢购的那家.我们的模式和它的一样,现在还没赢利,可将来起码有十几亿人民币的市值." "我开了小煤矿,但煤运不出去,上商学院之后受到启发,想搞模式创新,具体讲就是想在铁路边上搞个煤炭物流开发区,建一个大的物流和信息流平台,把分散的煤炭集中在我这个园区,这样和铁

一起谈.NET技术,WCF+WF双剑合璧构建微软的SOA系列(一):从一个简单的Demo开始

本系列文章将从实例出发,以实例结尾.由浅入深讲解在我们项目中如何使用WCF和WF.我们会发现使用WCF+WF将造就出其他技术无法达到的高度.最后我会将程序架到云端. 微软.net的3W(WPF.WCF.WF)战略如下图.WCF负责通信,WPF负责界面展示,WF负责处理业务逻辑,如下图. 本系列文章会主要用到上图中的所有技术,但是主要讲述如何使用WCF和WF来实现系统的中间层.看过亮剑的朋友知道李云龙常打胜仗,并不是他懂得很多很多的战争的理论知识,而是来自实战中的经验.所以本系列的文章以实战为核心