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

代码实现:

  WCF宿主(服务端)

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

 namespace Host
{
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallBackServices))]
public interface IServices
{
/// <summary>
/// 注册客户端信息
/// </summary>
[OperationContract(IsOneWay = false)]
void Register();
}
/// <summary>
/// 回调接口
/// </summary>
public interface ICallBackServices
{
/// <summary>
/// 服务像客户端发送信息(异步)
/// </summary>
/// <param name="Message"></param>
[OperationContract(IsOneWay = true)]
void SendMessage(string Message); /// <summary>
/// 服务端像客户端(异步)发送图片流
/// </summary>
/// <param name="messageEntity"></param>
[OperationContract(IsOneWay = true)]
void SendPicStream(MessageEntity messageEntity);
}
}

MessageEntity.cs 消息实体类

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization; namespace WcfDuplex
{
/// <summary>
/// 消息实体类
/// </summary>
[DataContract]
public class MessageEntity
{
[DataMember]
public string Content { get; set; } [DataMember]
public byte[] PicStream { get; set; }
}
}

Services.cs

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Configuration; namespace Host
{
/// <summary>
/// 实例使用Single,共享一个
/// 并发使用Mutiple, 支持多线程访问(一定要加锁)
/// </summary>
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Services : IServices
{
public static readonly string SendMessageType = ConfigurationManager.ConnectionStrings["SendMessageType"].ToString();
private static readonly object InstObj = new object();//单一实例
//public static List<ICallBackServices> RegList = null;
public static Dictionary<string, ICallBackServices> DicHost = null; //记录机器名称
public static Dictionary<string, ICallBackServices> DicHostSess = null;//记录Sessionid
public Services()
{
//RegList = new List<ICallBackServices>();
DicHost = new Dictionary<string, ICallBackServices>();
DicHostSess = new Dictionary<string, ICallBackServices>();
}
#region IServices 成员 public void Register()
{
ICallBackServices client = OperationContext.Current.GetCallbackChannel<ICallBackServices>();
string sessionid = OperationContext.Current.SessionId;//获取当前机器Sessionid--------------------------如果多个客户端在同一台机器,就使用此信息。
string ClientHostName = OperationContext.Current.Channel.RemoteAddress.Uri.Host;//获取当前机器名称-----多个客户端不在同一台机器上,就使用此信息。
OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing);//注册客户端关闭触发事件
if (SendMessageType.ToUpper() == "SESSIONID")
{
DicHostSess.Add(sessionid, client);//添加
}
else
{
DicHost.Add(ClientHostName, client); //添加
}
//RegList.Add(client);//添加
}
void Channel_Closing(object sender, EventArgs e)
{
lock (InstObj)//加锁,处理并发
{
//if (RegList != null && RegList.Count > 0)
// RegList.Remove((ICallBackServices)sender);
if (SendMessageType.ToUpper() == "SESSIONID")
{
if (DicHostSess != null && DicHostSess.Count > )
{
foreach (var d in DicHostSess)
{
if (d.Value == (ICallBackServices)sender)//删除此关闭的客户端信息
{
DicHostSess.Remove(d.Key);
break;
}
}
}
}
else
{
if (DicHost != null && DicHost.Count > ) //同上
{
foreach (var d in DicHost)
{
if (d.Value == (ICallBackServices)sender)
{
DicHost.Remove(d.Key);
break;
}
}
}
}
}
}
#endregion
}
}

服务端

Form1.cs

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using System.Threading;
using WcfDuplex;
using System.IO; namespace Host
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static readonly object InstObj = new object();
private static bool isval = true;
private void Form1_Load(object sender, EventArgs e)
{
ServiceHost host = new ServiceHost(typeof(Services));
host.Open();
this.Text = "wcf服务启动成功!"; #region 初始化ListBox
Thread thread = new Thread(new ThreadStart(delegate ///监听所有客户端连接,并添加到ListBox控件里
{
lock (InstObj)//加锁
{
while (true)
{ if (Services.SendMessageType.ToUpper() == "SESSIONID")
{
if (Services.DicHostSess != null || Services.DicHostSess.Count > )
{
this.Invoke(new MethodInvoker(delegate { this.listBox1.Items.Clear(); }));
foreach (var l in Services.DicHostSess)
{
this.Invoke(new MethodInvoker(delegate
{
this.listBox1.Items.Add(l.Key);
}));
}
}
}
else
{
if (Services.DicHost != null || Services.DicHost.Count > )
{
this.Invoke(new MethodInvoker(delegate { this.listBox1.Items.Clear(); }));
foreach (var l in Services.DicHost)
{
this.Invoke(new MethodInvoker(delegate
{
this.listBox1.Items.Add(l.Key);
}));
}
}
}
Thread.Sleep( * );
}
}
}));
thread.IsBackground = true;
thread.Start();
#endregion
} #region 推送
int i = ;
private void button1_Click(object sender, EventArgs e)
{
i++;
if (Services.DicHostSess == null || Services.DicHostSess.Count > )
{
if (this.listBox1.SelectedItem != null)
{
if (this.listBox1.SelectedItem.ToString() != "")
{
foreach (var d in Services.DicHostSess)
{
if (d.Key == this.listBox1.SelectedItem.ToString())
{
//d.Value.SendMessage(string.Format("Time: {0} message {1}", DateTime.Now, textBox1.Text.Trim()));
MessageEntity messageEntity = new MessageEntity();
if (i<)
{
string picPath = @"D:\download\wcf推送与广播\Host\Img\" + i + ".jpg";
messageEntity.PicStream = ImageDatabytes(picPath);
d.Value.SendPicStream(messageEntity);
}
}
}
}
}
else
{
MessageBox.Show("请选择要推送给哪台客户端");
i--;
return;
}
}
if (Services.DicHost != null || Services.DicHost.Count > )
{
if (this.listBox1.SelectedItem != null)
{
if (this.listBox1.SelectedItem.ToString() != "")
{
foreach (var d in Services.DicHost)
{
if (d.Key == this.listBox1.SelectedItem.ToString())
{
//d.Value.SendMessage(string.Format("Time: {0} message {1}", DateTime.Now, textBox1.Text.Trim()));
MessageEntity messageEntity = new MessageEntity();
if (i < )
{
string picPath = @"D:\download\wcf推送与广播\Host\Img\" + i + ".jpg";
messageEntity.PicStream = ImageDatabytes(picPath);
d.Value.SendPicStream(messageEntity);
}
}
}
}
}
else
{
MessageBox.Show("请选择要推送给哪台客户端");
i--;
return;
}
}
}
#endregion #region 广播方式
private void button2_Click(object sender, EventArgs e)
{
if (Services.SendMessageType.ToUpper() == "SESSIONID")//类型
{
foreach (var d in Services.DicHostSess)
{
d.Value.SendMessage(this.textBox1.Text);
}
}
else
{
foreach (var d in Services.DicHost)
{
d.Value.SendMessage(this.textBox1.Text);
}
}
}
#endregion #region 根据图片路径将图片转换为二进制流
/// <summary>
/// 根据图片路径将图片转换为二进制流
/// </summary>
/// <param name="FilePath"></param>
/// <returns></returns>
public static byte[] ImageDatabytes(string FilePath)
{
if (!File.Exists(FilePath))
return null;
Bitmap myBitmap = new Bitmap(Image.FromFile(FilePath)); using (MemoryStream curImageStream = new MemoryStream())
{
myBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Png);
curImageStream.Flush(); byte[] bmpBytes = curImageStream.ToArray();
//如果转字符串的话
//string BmpStr = Convert.ToBase64String(bmpBytes);
return bmpBytes;
}
}
#endregion }
}

WinFormClient.cs 客户端

客户端Form1.cs

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.ServiceModel; namespace WinFormClient
{ public partial class FormClient : Form
{
public FormClient()
{
InitializeComponent();
this.Text = "当前客户端编号为:"+DateTime.Now.ToString("yyyyMMddHHmmss");
try
{
Console.WriteLine("create object...");
CallBack back = new CallBack();
InstanceContext context = new InstanceContext(back);
ServiceReference1.ServicesClient client = new ServiceReference1.ServicesClient(context);
Console.WriteLine("regist.....");
back.showPic += new CallBack.ShowPic(ShowPicMethod);
client.Register();
Console.WriteLine("aucceeded");
//this.ReceivePic.Image = back.Pic;
}
catch (Exception ex) { Console.WriteLine(ex.Message); }
} public void ShowPicMethod(Bitmap bitmap)
{
this.ReceivePic.Image = bitmap;
}
} public class CallBack : ServiceReference1.IServicesCallback
{
public delegate void ShowPic(Bitmap bitmap);
public event ShowPic showPic; #region IServicesCallback 成员
public void SendMessage(string Message)
{
Console.WriteLine("[ClientTime{0:HHmmss}]Service Broadcast:{1}", DateTime.Now, Message);
} public void SendPicStream(ServiceReference1.MessageEntity messageEntity)
{
this.showPic(GetImage(messageEntity.PicStream));
}
#endregion #region 将图片二进制流转换为图片
public static Bitmap GetImage(byte[] ImageDatas)
{
try
{
//如果是字符串的话
//byte[] resultBytes = Convert.FromBase64String(ImageDatas);
using (MemoryStream ImageMS = new MemoryStream())
{
ImageMS.Write(ImageDatas, , ImageDatas.Length);
Bitmap resultBitmap = new Bitmap(ImageMS);
return resultBitmap;
}
}
catch
{
return null;
}
}
#endregion
}
}

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

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

  1. 我的WCF之旅(3):在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  2. 在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  3. 【OF框架】在Azure DevOps中配置项目持续集成CI服务,推送镜像到Azure容器注册表

    准备工作 开通Azure账号,具有开通服务权限,关键是里面要有钱. 开通Azure DevOps,能够创建组织和项目. 具备一定的DevOps知识,了解CICD概念.Docker基本操作. 一.创建& ...

  4. 用ASP.NET Core 1.0中实现邮件发送功能-阿里云邮件推送篇

    在上篇中用MailKit实现了Asp.net core 邮件发送功能,但一直未解决阿里云邮件推送问题,提交工单一开始的回复不尽如人意,比如您的网络问题,您的用户名密码不正确等,但继续沟通下阿里云客户还 ...

  5. node.js中使用socket.io + express进行实时消息推送

    socket.io是一个websocket库,包含客户端的js和服务端的node.js,可以在不同浏览器和移动设备上构建实时应用. 一.安装 socket.io npm install socket. ...

  6. 浅议Grpc传输机制和WCF中的回调机制的代码迁移

    浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...

  7. WCF初探-23:WCF中使用Message类(下)

    前言 在上一篇WCF中使用Message类(上)中,文章介绍了WCF中使用Message类的基本知识和怎样创建消息,本文是承接上一篇文章,如果想要更好的阅读本文,请先阅读上一篇文章.在这篇文章中,我将 ...

  8. Android、iOS和Windows Phone中的推送技术

    推送并不是什么新技术,这种技术在互联网时代就已经很流行了.只是随着进入移动互联网时代,推送技术显得更加重要.因为在智能手机中,推送从某种程度上,可以取代使用多年的短信,而且与短信相比,还可以向用户展示 ...

  9. APNS IOS 消息推送沙盒模式和发布模式

    在做.NET向IOS设备的App进行消息推送时候,采用的是PushSharp开源类库进行消息的推送,而在开发过程中,采用的是测试版本的app,使用的是测试的p12证书采用的是ApnsConfigura ...

随机推荐

  1. 框架-spring源码分析(一)

    框架-spring源码分析(一) 参考: https://www.cnblogs.com/heavenyes/p/3933642.html http://www.cnblogs.com/BINGJJF ...

  2. Redis之Sorted Set 有序集合

    Redis Sorted Set 有序集合 Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员. 不同的是每个元素都会关联一个double类型的分数.redis正是通过分 ...

  3. Redis之持久化

    Redis 持久化 提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的所有数据进 ...

  4. Gym 101246J Buoys(三分查找)

    http://codeforces.com/gym/101246/problem/J 题意: 给定x轴上的n个点的坐标,按顺序从左到右给出,现在要使得每个点的间距相同,可以移动每个点的坐标,但是不能改 ...

  5. Gym 101246D Fire in the Country(dfs求SG函数)

    http://codeforces.com/gym/101246/problem/D 题意: 给定一个无向有环图,大火从1点开始,每个时间点与它相邻的点也将会着火,现在有两个人轮流操作机器人,机器人从 ...

  6. POJ 1047 Round and Round We Go

    https://vjudge.net/problem/POJ-1047 题意: 给一个整数,它的长度为n,从1开始一直到n和该整数相乘,判断每次结果是否和原来的整数是循环的. 思路: 大整数的乘法. ...

  7. python strip()函数 os.popen()

    函数原型 声明:s为字符串,rm为要删除的字符序列 s.strip(rm) 删除s字符串中开头.结尾处,位于 rm删除序列的字符 s.lstrip(rm) 删除s字符串中开头处,位于 rm删除序列的字 ...

  8. [原][osgearth]API加载earth文件的解析

    参考:http://blog.csdn.net/cccstudyer/article/details/17691893 通过\src\osgEarthDrivers\earth\ReaderWrite ...

  9. vue全家桶实现笔记本功能

    一个通过vue实现的练手小项目,数据保存和导出通过node进行处理 成品截图: 安装vue-cli,webpack: cnpm install webpack -g cnpm install vue- ...

  10. Total Defense Anti-Virus – 免费6个月

    Total Defense Anti-Virus 具有病毒和间谍软件保护,免费的专家远程安装和设置,快速扫描引擎不会拖慢电脑速度,基于云保护.高级Rootkit保护,自动扫描驱动器和内存等等.官方网站 ...