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

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

  效果

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

image

  实现

  双工的服务契约定义:

 
 
[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、由于客户端是定时上传视频流,而非长连接方式,需要不停的调用服务器来上传视频,有些耗资源,并且有时会出现下面的异常,猜想是由于不停的连接导致。

image

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

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

目录
相关文章
|
物联网 Linux 开发工具
Net Core 跨平台应用使用串口、串口道通信,可能出现的问题、更简洁的实现方法
Net Core 跨平台应用使用串口、串口道通信,可能出现的问题、更简洁的实现方法
346 0
Net Core 跨平台应用使用串口、串口道通信,可能出现的问题、更简洁的实现方法
|
监控 物联网 API
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
MQTT广泛应用于工业物联网、智能家居、各类智能制造或各类自动化场景等。MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,在很多受限的环境下,比如说机器与机器通信、机器与物联网通信等。好了,科普的废话不多说,下面直接通过.NET环境来实现一套MQTT通信demo,实现服务端与客户端的双边消息发布与订阅的功能和演示。
962 0
【.NET+MQTT】.NET6 环境下实现MQTT通信,以及服务端、客户端的双边消息订阅与发布的代码演示
|
7月前
|
网络协议 安全 Java
.NET网络编程——TCP通信
.NET网络编程——TCP通信
58 0
|
9月前
|
消息中间件 安全 数据库连接
.NET开发问题记录——TransactionScope出错:“与基础事务管理器的通信失败”的解决方法
.NET开发问题记录——TransactionScope出错:“与基础事务管理器的通信失败”的解决方法
186 0
|
缓存 前端开发 JavaScript
采用.Net Core技术框架开发的医院云LIS平台源码,B/S架构
基于B/S架构的医学实验室检验系统源码,整个系统的运行基于WEB层面,只需要在对应的工作台安装一个浏览器软件有外网即可访问。全套系统采用云部署模式,部署一套可支持多家医院检验科共同使用。 采用.Net Core新的技术框架、DEV报表、前端js封装、分布式文件存储、分布式缓存等,支持LIS独立部署,Docker部署等多种方式。
|
存储 数据采集 网络协议
【.NET6+Modbus】Modbus TCP协议解析、仿真环境以及基于.NET实现基础通信
随着工业化的发展,目前越来越多的开发,从互联网走向传统行业。其中,工业领域也是其中之一,包括各大厂也都在陆陆续续加入工业4.0的进程当中。
295 0
【.NET6+Modbus】Modbus TCP协议解析、仿真环境以及基于.NET实现基础通信
|
XML 网络协议 IDE
WCF基础教程(三)——WCF通信过程及配置文件解析
WCF基础教程(三)——WCF通信过程及配置文件解析
294 0
WCF基础教程(三)——WCF通信过程及配置文件解析
|
存储 开发框架 JavaScript
『SignalR』.NET使用 SignalR 进行实时通信初体验
📣读完这篇文章里你能收获到 - 你将对SignalR有了初步的认识及体会 - 对于哪些场景适用SignalR以及如何接入使用 - SignalR的代码入门级Demo实际案例
461 0
『SignalR』.NET使用 SignalR 进行实时通信初体验
|
安全 NoSQL MongoDB
.Net线程同步技术解读
C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。
.Net线程同步技术解读
|
移动开发 负载均衡 前端开发
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
144 0
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)