参考资料地址: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. SPOJ BALNUM Balanced Numbers(数位DP+状态压缩)题解

    思路: 把0~9的状态用3进制表示,数据量3^10 代码: #include<cstdio> #include<map> #include<set> #includ ...

  2. HDU 2896 病毒侵袭(AC自动机)题解

    题意:给你n个模式串,再给你m个主串,问你每个主串中有多少模式串,并输出是哪些.注意一下,这里给的字符范围是可见字符0~127,所以要开130左右. 思路:用字典树开的时候储存编号,匹配完成后set记 ...

  3. MyBatis的简单入门学习

    一个新知识开始是最难学的.(万事开头难) MyBatis大体分三层,接口层,数据处理层,基础支撑层. 其中接口层不是java中的那个interface,而是框架和程序员之间的对接.一个API,程序员可 ...

  4. jvm 内存调整

    top查看java占用的内存比较多 top - :: up days, :, user, load average: 0.03, 0.05, 0.05 Tasks: total, running, s ...

  5. Pro Git读书笔记 - Git 常用命令

    在工作目录中初始化新仓库 要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行git init 检查当前文件状态 要查看哪些文件处于什么状态,可以用git status命令 将工作文件 ...

  6. nodejs项目的model操作mongo

    想想以前学习hibernate的时候,学习各种表和表之间的映射关系等一对多,多对一,多对多,后来到了工作中,勇哥告诉我, 那时在学习的时候,公司中都直接用外键关联. 这里我们学习下,如何在Nodejs ...

  7. C#通过WMI读取MAC地址

    该方法依赖WMI的系统服务,该服务一般不会被关闭;但如果系统服务缺失或者出现问题,该方法无法取得MAC地址,需要重启Windows Management Instrumentation服务. publ ...

  8. 使用POI动态更新导出的EXCEL模板中的列

    基本思路: 1.从附件服务器上取得模板的流文件 2.拿到流文件之后再使用workbook.write(outs);方法改变流文件中的数据. else if (pageContext.getParame ...

  9. spring的懒加载和depends-on

    ①延迟初始化Bean(惰性初始化Bean)是指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean.  配置方式很简单只需在<bean>标签上指定 “lazy-init” 属性 ...

  10. qt Cannot connect creator comm socket /tmp/qt_temp.S26613/stub-socket: No such

    Tool->Options->Environment->General 将terminal改为 xterm -e