图片同步

  尝试这样一个思路,用UDP组播的方式,由一个发送端在组内发布时间计数,所有接收端以此计数作为相对时间,来定位当前应该显示哪张图片;

  发送端代码如下(此段代码为站在巨人的肩膀上,引用自小白的Blog):

ExpandedBlockStart.gif 发送端
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Net;
using  System.Net.Sockets;

namespace  CommandLine {
    
class  Program {
        
static   void  Main( string [] args) {
            IPAddress ip 
=  IPAddress.Parse( " 224.1.2.3 " );
            Socket s 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 
1 );
            IPEndPoint ipep 
=   new  IPEndPoint(ip,  5000 );

            Console.WriteLine(
" Begin Connect... " );

            
int  interval  =   20 ;
            
int  sum  =   86400000   /   20 ;
            
int  num  =   0 ;
            timer 
=   new  System.Timers.Timer(interval);
            timer.Elapsed 
+=  (o1, e1)  =>  {
                
string  str  =  num.ToString();
                
byte [] buff  =  Encoding.ASCII.GetBytes(str);
                s.SendTo(buff, buff.Length, SocketFlags.None, ipep);
                Console.WriteLine(
string .Format( " Send=>{0} " , str));
                num
++ ;
                
if  (num  >=  sum) num  =   0 ;
            };
            timer.Start();

            Console.WriteLine(
" == End == " );
            Console.ReadKey();

            timer.Stop();
            s.Close();
        }

        
private   static  System.Timers.Timer timer;
    }
}

 

  接收端代码如下:

ExpandedBlockStart.gif 接收端
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Net.Sockets;
using  System.Net;
using  System.Threading;

namespace  WpfApplication {
    
public   class  TimeManager {
        
public   static  TimeManager Instance {  get  {  return  instance; }  set  { instance  =  value; } }
        
public   int  Count {  get  {  return  count; }  set  { count  =  value; } }

        
private  TimeManager() { }

        
public   void  Start() {
            s 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            IPEndPoint ipep 
=   new  IPEndPoint(IPAddress.Any,  5000 );
            s.Bind(ipep);

            s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership,
                
new  MulticastOption(IPAddress.Parse( " 224.1.2.3 " ), IPAddress.Any));

            
new  Thread( new  ThreadStart(()  =>  {
                
while  ( ! needExit) {
                    
try  {
                        
byte [] b  =   new   byte [ 4 ];
                        s.Receive(b, 
4 , SocketFlags.None);
                        
string  str  =  Encoding.ASCII.GetString(b,  0 , b.Length);
                        count 
=  Convert.ToInt32(str);
                    } 
catch  { }
                }
            })).Start();
        }

        
public   void  Stop() {
            needExit 
=   true ;
            s.Close();
        }

        
private   static  TimeManager instance  =   new  TimeManager();
        
private   int  count;
        
private  Socket s;
        
private   bool  needExit  =   false ;
    }
}

 

  然后在前端,将这个时间计数作为标准来定位和显示图片,代码如下:

 

ExpandedBlockStart.gif 显示端
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Windows;
using  System.Windows.Controls;
using  System.Windows.Data;
using  System.Windows.Documents;
using  System.Windows.Input;
using  System.Windows.Media;
using  System.Windows.Media.Imaging;
using  System.Windows.Navigation;
using  System.Windows.Shapes;
using  System.IO;
using  System.Threading;
using  System.Runtime.InteropServices;

namespace  WpfApplication {
    
///   <summary>
    
///  Interaction logic for MainWindow.xaml
    
///   </summary>
     public   partial   class  MainWindow : Window {
        
public  MainWindow() {
            InitializeComponent();
        }

        
private   void  Window_Loaded( object  sender, RoutedEventArgs e) {
            FullScreen();

            TimeManager.Instance.Start();

            
foreach  ( string  each  in  Directory.GetFiles( " ./ " )) {
                
if  (System.IO.Path.GetExtension(each).ToLower()  ==   " .jpg " ) {
                    files.Add(System.IO.Path.GetFullPath(each));
                }
            }

            
new  Thread( new  ThreadStart(ShowImage)).Start();
        }

        
private   void  ShowImage() {
            
if  (files.Count  >   0 ) {
                
while  ( ! needExit) {
                    
try  {
                        
int  now  =  TimeManager.Instance.Count;
                        
int  count  =  files.Count;
                        
int  offset  =  now  %  (count  *   100 );
                        
int  index  =  offset  /   100 ;
                        
string  filename  =  files[index];

                        
this .Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,  new  EventHandler((o1, e1)  =>  {
                            image1.Source 
=   new  BitmapImage( new  Uri(filename));
                        }), 
null null );

                        
// int interval = 500 - offset % 500;
                        Thread.Sleep( 20 );
                    } 
catch  (Exception ex) {
                        MessageBox.Show(ex.ToString());
                    }
                }
            }
        }

        
private   void  Window_Closing( object  sender, System.ComponentModel.CancelEventArgs e) {
            needExit 
=   true ;
            TimeManager.Instance.Stop();
        }

        
private   void  Window_KeyDown( object  sender, KeyEventArgs e) {
            
if  (e.Key  ==  Key.F5) {
                
if  (fullscreen) {
                    PartScreen();
                } 
else  {
                    FullScreen();
                }
            }
        }

        
private   void  Window_SizeChanged( object  sender, SizeChangedEventArgs e) {
            
//
        }

        
private   void  FullScreen() {
            
this .WindowStyle  =  WindowStyle.None;
            
this .WindowState  =  WindowState.Maximized;
            
this .WindowStartupLocation  =  WindowStartupLocation.CenterScreen;
            
this .Topmost  =   true ;
            ShowCursor(
0 );
            fullscreen 
=   true ;
        }

        
private   void  PartScreen() {
            
// this.WindowState = lastBorder;
            
// this.Location = lastLocation;
            
// this.RenderSize = lastSize;
            
// this.Topmost = false;
            
// ShowCursor(1);
            
// fullscreen = false;
        }

        [DllImport(
" user32.dll " , EntryPoint  =   " ShowCursor " , CharSet  =  CharSet.Auto)]
        
public   extern   static   void  ShowCursor( int  status);

        
private  List < string >  files  =   new  List < string > ();
        
private   bool  needExit  =   false ;
        
private   bool  fullscreen;
        
private  Point lastLocation;
        
private  Size lastSize;
        
private  WindowState lastBorder;
    }
}

 

   然而在两个设备上测试后发现实际的效果却不尽如人意,会出现同步->A超前->同步->B超前的现象,如此摇摆;复看了一遍小白的那篇文章,发现有这样一句说明:“UDP组播是采用的无连接,数据报的连接方式,所以是不可靠的。也就是数据能不能到达接受端和数据到达的顺序都是不能保证的。”这是否说明完全依靠UDP组播的精确同步也是做不到的呢?

  To be continued...

转载于:https://www.cnblogs.com/acexist/archive/2010/05/21/1741125.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值