使用用WCF中的双工(Duplex)模式将广告图片推送到每个Winform客户端机子上

参考资料地址:http://www.cnblogs.com/server126/archive/2011/08/11/2134942.html

代码实现:

  WCF宿主(服务端)

IServices.cs 服务契约(其实就是接口)

 1 namespace Host
 2 {
 3     [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallBackServices))]
 4     public interface IServices
 5     {
 6        /// <summary>
 7        /// 注册客户端信息
 8        /// </summary>
 9         [OperationContract(IsOneWay = false)]
10         void Register();
11     }
12     /// <summary>
13     ///  回调接口
14     /// </summary>
15     public interface ICallBackServices
16     {
17         /// <summary>
18         /// 服务像客户端发送信息(异步)
19         /// </summary>
20         /// <param name="Message"></param>
21         [OperationContract(IsOneWay = true)]
22         void SendMessage(string Message);
23 
24         /// <summary>
25         /// 服务端像客户端(异步)发送图片流
26         /// </summary>
27         /// <param name="messageEntity"></param>
28         [OperationContract(IsOneWay = true)]
29         void SendPicStream(MessageEntity messageEntity);
30     }
31 } 
View Code

MessageEntity.cs 消息实体类

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Runtime.Serialization;
 6 
 7 namespace WcfDuplex
 8 {
 9     /// <summary>
10     /// 消息实体类
11     /// </summary>
12     [DataContract]
13     public class MessageEntity
14     {
15         [DataMember]
16         public string Content { get; set; }
17 
18         [DataMember]
19         public byte[] PicStream { get; set; }
20     }
21 }

Services.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 using System.Configuration;
 7 
 8 namespace Host
 9 {
10     /// <summary>
11     ///  实例使用Single,共享一个
12     ///  并发使用Mutiple, 支持多线程访问(一定要加锁)
13     /// </summary>
14     [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
15     public class Services : IServices
16     {
17         public static readonly string SendMessageType = ConfigurationManager.ConnectionStrings["SendMessageType"].ToString();
18         private static readonly object InstObj = new object();//单一实例
19         //public static List<ICallBackServices> RegList = null;
20         public static Dictionary<string, ICallBackServices> DicHost = null; //记录机器名称
21         public static Dictionary<string, ICallBackServices> DicHostSess = null;//记录Sessionid
22         public Services()
23         {
24             //RegList = new List<ICallBackServices>();
25             DicHost = new Dictionary<string, ICallBackServices>();
26             DicHostSess = new Dictionary<string, ICallBackServices>();
27         }
28         #region IServices 成员
29 
30         public void Register()
31         {
32             ICallBackServices client = OperationContext.Current.GetCallbackChannel<ICallBackServices>();
33             string sessionid = OperationContext.Current.SessionId;//获取当前机器Sessionid--------------------------如果多个客户端在同一台机器,就使用此信息。
34             string ClientHostName = OperationContext.Current.Channel.RemoteAddress.Uri.Host;//获取当前机器名称-----多个客户端不在同一台机器上,就使用此信息。
35             OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing);//注册客户端关闭触发事件
36             if (SendMessageType.ToUpper() == "SESSIONID")
37             {
38                 DicHostSess.Add(sessionid, client);//添加
39             }
40             else
41             {
42                 DicHost.Add(ClientHostName, client); //添加
43             }
44             //RegList.Add(client);//添加
45         }
46         void Channel_Closing(object sender, EventArgs e)
47         {
48             lock (InstObj)//加锁,处理并发
49             {
50                 //if (RegList != null && RegList.Count > 0)
51                 //    RegList.Remove((ICallBackServices)sender); 
52                 if (SendMessageType.ToUpper() == "SESSIONID")
53                 {
54                     if (DicHostSess != null && DicHostSess.Count > 0)
55                     {
56                         foreach (var d in DicHostSess)
57                         {
58                             if (d.Value == (ICallBackServices)sender)//删除此关闭的客户端信息
59                             {
60                                 DicHostSess.Remove(d.Key);
61                                 break;
62                             }
63                         }
64                     }
65                 }
66                 else
67                 {
68                     if (DicHost != null && DicHost.Count > 0) //同上
69                     {
70                         foreach (var d in DicHost)
71                         {
72                             if (d.Value == (ICallBackServices)sender)
73                             {
74                                 DicHost.Remove(d.Key);
75                                 break;
76                             }
77                         }
78                     }
79                 }
80             }
81         }
82         #endregion
83     }
84 } 
View Code

服务端

Form1.cs

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.ServiceModel;
 10 using System.Threading;
 11 using WcfDuplex;
 12 using System.IO;
 13 
 14 namespace Host
 15 {
 16     public partial class Form1 : Form
 17     {
 18         public Form1()
 19         {
 20             InitializeComponent();
 21         }
 22         private static readonly object InstObj = new object();
 23         private static bool isval = true;
 24         private void Form1_Load(object sender, EventArgs e)
 25         {
 26             ServiceHost host = new ServiceHost(typeof(Services));
 27             host.Open();
 28             this.Text = "wcf服务启动成功!";
 29 
 30             #region 初始化ListBox
 31             Thread thread = new Thread(new ThreadStart(delegate   ///监听所有客户端连接,并添加到ListBox控件里
 32             {
 33                 lock (InstObj)//加锁
 34                 {
 35                     while (true)
 36                     {
 37 
 38                         if (Services.SendMessageType.ToUpper() == "SESSIONID")
 39                         {
 40                             if (Services.DicHostSess != null || Services.DicHostSess.Count > 0)
 41                             {
 42                                 this.Invoke(new MethodInvoker(delegate { this.listBox1.Items.Clear(); }));
 43                                 foreach (var l in Services.DicHostSess)
 44                                 {
 45                                     this.Invoke(new MethodInvoker(delegate
 46                                     {
 47                                         this.listBox1.Items.Add(l.Key);
 48                                     }));
 49                                 }
 50                             }
 51                         }
 52                         else
 53                         {
 54                             if (Services.DicHost != null || Services.DicHost.Count > 0)
 55                             {
 56                                 this.Invoke(new MethodInvoker(delegate { this.listBox1.Items.Clear(); }));
 57                                 foreach (var l in Services.DicHost)
 58                                 {
 59                                     this.Invoke(new MethodInvoker(delegate
 60                                     {
 61                                         this.listBox1.Items.Add(l.Key);
 62                                     }));
 63                                 }
 64                             }
 65                         }
 66                         Thread.Sleep(1000 * 10);
 67                     }
 68                 }
 69             }));
 70             thread.IsBackground = true;
 71             thread.Start();
 72             #endregion
 73         }
 74 
 75         #region 推送
 76         int i = 0;
 77         private void button1_Click(object sender, EventArgs e)
 78         {
 79             i++;
 80             if (Services.DicHostSess == null || Services.DicHostSess.Count > 0)
 81             {
 82                 if (this.listBox1.SelectedItem != null)
 83                 {
 84                     if (this.listBox1.SelectedItem.ToString() != "")
 85                     {
 86                         foreach (var d in Services.DicHostSess)
 87                         {
 88                             if (d.Key == this.listBox1.SelectedItem.ToString())
 89                             {
 90                                 //d.Value.SendMessage(string.Format("Time: {0} message {1}", DateTime.Now, textBox1.Text.Trim()));
 91                                 MessageEntity messageEntity = new MessageEntity();
 92                                 if (i<4)
 93                                 {
 94                                     string picPath = @"D:downloadwcf推送与广播HostImg" + i + ".jpg";
 95                                     messageEntity.PicStream = ImageDatabytes(picPath);
 96                                     d.Value.SendPicStream(messageEntity);
 97                                 }
 98                             }
 99                         }
100                     }
101                 }
102                 else 
103                 { 
104                     MessageBox.Show("请选择要推送给哪台客户端");
105                     i--;
106                     return; 
107                 }
108             }
109             if (Services.DicHost != null || Services.DicHost.Count > 0)
110             {
111                 if (this.listBox1.SelectedItem != null)
112                 {
113                     if (this.listBox1.SelectedItem.ToString() != "")
114                     {
115                         foreach (var d in Services.DicHost)
116                         {
117                             if (d.Key == this.listBox1.SelectedItem.ToString())
118                             {
119                                 //d.Value.SendMessage(string.Format("Time: {0} message {1}", DateTime.Now, textBox1.Text.Trim()));
120                                 MessageEntity messageEntity = new MessageEntity();
121                                 if (i < 4)
122                                 {
123                                     string picPath = @"D:downloadwcf推送与广播HostImg" + i + ".jpg";
124                                     messageEntity.PicStream = ImageDatabytes(picPath);
125                                     d.Value.SendPicStream(messageEntity);
126                                 }
127                             }
128                         }
129                     }
130                 }
131                 else 
132                 { 
133                     MessageBox.Show("请选择要推送给哪台客户端");
134                     i--;
135                     return; 
136                 }
137             }
138         } 
139         #endregion
140         
141         #region 广播方式
142         private void button2_Click(object sender, EventArgs e)
143         {
144             if (Services.SendMessageType.ToUpper() == "SESSIONID")//类型
145             {
146                 foreach (var d in Services.DicHostSess)
147                 {
148                     d.Value.SendMessage(this.textBox1.Text);
149                 }
150             }
151             else
152             {
153                 foreach (var d in Services.DicHost)
154                 {
155                     d.Value.SendMessage(this.textBox1.Text);
156                 }
157             }
158         } 
159         #endregion
160 
161         #region 根据图片路径将图片转换为二进制流
162         /// <summary>
163         /// 根据图片路径将图片转换为二进制流
164         /// </summary>
165         /// <param name="FilePath"></param>
166         /// <returns></returns>
167         public static byte[] ImageDatabytes(string FilePath)
168         {
169             if (!File.Exists(FilePath))
170                 return null;
171             Bitmap myBitmap = new Bitmap(Image.FromFile(FilePath));
172 
173             using (MemoryStream curImageStream = new MemoryStream())
174             {
175                 myBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Png);
176                 curImageStream.Flush();
177 
178                 byte[] bmpBytes = curImageStream.ToArray();
179                 //如果转字符串的话
180                 //string BmpStr = Convert.ToBase64String(bmpBytes);
181                 return bmpBytes;
182             }
183         } 
184         #endregion
185 
186     }
187 }
View Code

WinFormClient.cs 客户端

客户端Form1.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.IO;
10 using System.ServiceModel;
11 
12 namespace WinFormClient
13 {
14     
15 
16     public partial class FormClient : Form
17     {
18         public FormClient()
19         {
20             InitializeComponent();
21             this.Text = "当前客户端编号为:"+DateTime.Now.ToString("yyyyMMddHHmmss");
22             try
23             {
24                 Console.WriteLine("create object...");
25                 CallBack back = new CallBack();
26                 InstanceContext context = new InstanceContext(back);
27                 ServiceReference1.ServicesClient client = new ServiceReference1.ServicesClient(context);
28                 Console.WriteLine("regist.....");
29                 back.showPic += new CallBack.ShowPic(ShowPicMethod);
30                 client.Register();
31                 Console.WriteLine("aucceeded");
32                 //this.ReceivePic.Image = back.Pic;
33             }
34             catch (Exception ex) { Console.WriteLine(ex.Message); }
35         }
36 
37         public void ShowPicMethod(Bitmap bitmap)
38         {
39             this.ReceivePic.Image = bitmap;
40         }
41     }
42 
43     public class CallBack : ServiceReference1.IServicesCallback
44     {
45         public delegate void ShowPic(Bitmap bitmap);
46         public event ShowPic showPic;
47 
48         #region IServicesCallback 成员
49         public void SendMessage(string Message)
50         {
51             Console.WriteLine("[ClientTime{0:HHmmss}]Service Broadcast:{1}", DateTime.Now, Message);
52         }
53 
54         public void SendPicStream(ServiceReference1.MessageEntity messageEntity)
55         {
56             this.showPic(GetImage(messageEntity.PicStream));
57         }
58         #endregion
59 
60         #region 将图片二进制流转换为图片
61         public static Bitmap GetImage(byte[] ImageDatas)
62         {
63             try
64             {
65                 //如果是字符串的话
66                 //byte[] resultBytes = Convert.FromBase64String(ImageDatas);
67                 using (MemoryStream ImageMS = new MemoryStream())
68                 {
69                     ImageMS.Write(ImageDatas, 0, ImageDatas.Length);
70                     Bitmap resultBitmap = new Bitmap(ImageMS);
71                     return resultBitmap;
72                 }
73             }
74             catch
75             {
76                 return null;
77             }
78         }
79         #endregion
80     }
81 }
View Code

 Demo下载地址:http://files.cnblogs.com/files/wgx0428/wcf%E6%8E%A8%E9%80%81%E4%B8%8E%E5%B9%BF%E6%92%AD.zip

原文地址:https://www.cnblogs.com/wgx0428/p/3539568.html