参考资料地址: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 }
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 }
服务端
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:\download\wcf推送与广播\Host\Img\" + 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:\download\wcf推送与广播\Host\Img\" + 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 }
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 }
Demo下载地址:http://files.cnblogs.com/wgx0428/wcf%E6%8E%A8%E9%80%81%E4%B8%8E%E5%B9%BF%E6%92%AD.zip