是一些代码修改,会比较枯燥,所以没接着写,不过有昨天有网页表示对象棋在线演示中的 对战视频 感兴趣,希望可以提前看到代码,所以本次就提前写里面的对战视频这一块。
由于对战视频采用控制台程序,并没有在服务器运行,所以在线演示版本里一进入显示是显示“未链接”的提示。 作者:路过秋天 博客:http://cyq1162.cnblogs.com/
一:对战视频 简单原理:
1 :由于Silverlight不支持点对点方式传输,因此只能通过服务器中转方式进行。2 :视频的传输是图片字节,因此压缩图片是相当必要的。
3 :中间的服务选什么?一开始我是在尝试使用WCF的tcp方式,后来折腾配置文件太痛苦,直接转使用Socket通讯,一来有性能优势,二来减少折腾。
二:对战视频 步骤解析:
1 :客户端打开视频2 :客户端向远端Socket注册[按规则定好的]编号[服务端根据编号查要转发的对象]
3 :服务端接收编号并注册,收集一系列编号列表。
4 :客户端发送视频
5 :服务端接收视频,并根据规则查找另一个编号,将视频字节转发
6 :另一个客户端接收视频并显示
三:对战视频 具体实施
1:如何打开视频
在Siverlight中打开视频相当的简单,都有注释,就不多解说了代码如下:
private voID btnStart_Click( object sender, RoutedEventArgs e){
VIDeoCaptureDevice device = CaptureDeviceConfiguration.GetDefaultVIDeoCaptureDevice();//获取系统默认视频设备
if (device == null )
{
MessageBox.Show( " 没有检测到设备! " );
return ;
}
if (CaptureDeviceConfiguration.RequestDeviceAccess()) // 请求设备
{
CaptureSource source = new CaptureSource() // 数据源
{
VIDeoCaptureDevice = device //设置属性,将 数据源绑定到视频
};
VIDeoBrush brush = new VIDeoBrush(); // 视频刷子
brush.SetSource(source); // 视频刷子从视频源获取视频
source.Start();
myVIDeo.Fill = brush; // 最后填充Rectangle [myVIDeo只是一个普通Rectangle]
}
}
界面Rectangle代码:
< Canvas WIDth ="160" Height ="160" Background ="Red" margin ="22,109,518,531" @R_419_6889@ ="canVIDeo" >< Rectangle Height ="160" @R_419_6889@ ="myVIDeo" stroke ="Black" strokeThickness ="1" WIDth ="160" Canvas.left ="0" Canvas.top ="0" />
</ Canvas >
运行后我们看下效果,[这里用了本地的虚拟视频,开了3个浏览器并排截了图,第4张是不一样的哦],中间提示确认是否打开视频就不截图了:
@H_301_404@
2:Silverlight如何使用Socket进行通讯
由于Silverlight一般是不允许跨域通讯,因此,其Socket通讯也要比普通的Socket通讯麻烦一小点,不过这麻烦的小点只表现在服务端。下面进行代码解析:以下代码将一步扣一步,具体的连环扣如下:建立链接-》注册编号-》开新线程待接收视频-》收到视频处理显示。
2.1:与远程建立链接:
Socket vIDeoSocket; // 全局定义一个Socketprivate voID btnSocketConn_Click( object sender, RoutedEventArgs e)
{
if (vIDeoSocket == null ) // 实例化Socket
{
vIDeoSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
socketasynceventargs socketEvent = new socketasynceventargs() // 通讯参数
{
RemoteEndPoint = new IPEndPoint(IPAddress.Parse( " 192.168.0.48 " ), 4505 ), // 设置连接的IP与端口
};
socketEvent.Completed += new EventHandler < socketasynceventargs > (socketEvent_Completed);
vIDeoSocket.ConnectAsync(socketEvent); // 异步链接到远程
}
voID socketEvent_Completed( object sender, socketasynceventargs e) // 链接完成后
{
// 这里要写点什么呢?
}
2.2:注册编号[这里的规则是“房间号+棋手颜色值”]
voID socketEvent_Completed( object sender, socketasynceventargs e){
if (e.socketError == SocketError.Success)
{
byte [] buffer = System.Text.EnCoding.UTF8.GetBytes( " 11 " ); // 我的编号,11=1房间+红色玩家1,对应的就是12=1房间+黑色玩家2
socketasynceventargs dataEvent = new socketasynceventargs();
dataEvent.SetBuffer(buffer, 0 , buffer.Length);
dataEvent.Completed += new EventHandler < socketasynceventargs > (dataEvent_Completed);
vIDeoSocket.SendAsync(dataEvent); // 发送号码到服务端注册
}
}
voID dataEvent_Completed( object sender, socketasynceventargs e)
{
// 号码发送过去了,接下这里干点什么呢?
}
2.3:开新线程,等待接收对方视频
voID dataEvent_Completed( object sender, socketasynceventargs e){
System.Threading.Thread thread = new System.Threading.Thread( new System.Threading.ThreadStart(Receive)); // 开启线程
thread.Start();
}
voID Receive() // 接收视频处理
{
byte [] buffer = new byte [ 1024 * 1024 ];
while ( true )
{
socketasynceventargs receiveEvent = new socketasynceventargs();
receiveEvent.SetBuffer(buffer, buffer.Length);
receiveEvent.Completed += new EventHandler < socketasynceventargs > (receiveEvent_Completed);
vIDeoSocket.ReceiveAsync(receiveEvent);
System.Threading.Thread.Sleep( 50 ); // 小小休眠一下,不要干活太累
}
}
voID receiveEvent_Completed( object sender, socketasynceventargs e)
{
// 如果收到视频,我们要怎么处理呢?
}
2.4:将视频显示出来,需要用主线程来 *** 作
SynchronizationContext syn = SynchronizationContext.Current; // 获取当前主线程voID receiveEvent_Completed( object sender, socketasynceventargs e)
{
byte [] data = e.Buffer;
if (data[ 0 ] > 0 )
{
syn.Post(SetVIDeo, data); // 由于新线程无法对控件进行 *** 作,需要主线程来调用
}
}
voID SetVIDeo( object data) // 设置视频
{
MemoryStream stream = null ;
WriteableBitmap img = null ;
try
{
stream = new MemoryStream(data as byte []);
img = new WriteableBitmap( 160 , 160 );
img.SetSource(stream);
imgVIDeo.source = img; // 直接赋下值,就设置好了。
}
catch
{
return ;
}
finally
{
if (stream != null )
{
stream.Close();
}
if (img != null )
{
img = null ;
}
}
}
上面的imgVIDeo为:
< Image Height ="160" HorizontalAlignment ="left" margin ="207,0" @R_419_6889@ ="imgVIDeo" Stretch ="Fill" VerticalAlignment ="top" WIDth ="160" />至此,我们连续完成了“打开视频—》注册—》等待接收-》接收时开主线程显示”,我们提前看一下完成后接收时的效果图:
红色块是显示视频的区域,当前图片说明左侧没有开启视频,只是开了接收,右侧开了视频,并发送视频。
下面再顺路看一下开启的服务端中转Socket的运行:
OK,本节就先到此,下节我们再讲“视频图片的压缩与发送”+服务端处理中转流程
最后:谢谢大家对本系列的喜欢,谢谢支持~
PS:传说点一下推荐会有10个园豆,喜欢麻烦点一下“推荐”,thank you very much!!
总结以上是内存溢出为你收集整理的Silverlight+WCF 实战-网络象棋最终篇之对战视频-上篇[客户端开启视频/注册编号/接收视频](五)全部内容,希望文章能够帮你解决Silverlight+WCF 实战-网络象棋最终篇之对战视频-上篇[客户端开启视频/注册编号/接收视频](五)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)