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

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

发送端
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;
    }
}

 

  接收端代码如下:

接收端
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;
    }
}

 

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

 

显示端
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));
                        }), 
nullnull);

                        
//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...

posted on 2010-05-21 17:52  ю意思я  阅读(270)  评论(0编辑  收藏  举报