使用用WCF中的双工(Duplex)模式将广告图片推送到每个Winform客户端机子上
参考资料地址: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客户端机子上的更多相关文章
- 我的WCF之旅(3):在WCF中实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
- 在WCF中实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
- 【OF框架】在Azure DevOps中配置项目持续集成CI服务,推送镜像到Azure容器注册表
准备工作 开通Azure账号,具有开通服务权限,关键是里面要有钱. 开通Azure DevOps,能够创建组织和项目. 具备一定的DevOps知识,了解CICD概念.Docker基本操作. 一.创建& ...
- 用ASP.NET Core 1.0中实现邮件发送功能-阿里云邮件推送篇
在上篇中用MailKit实现了Asp.net core 邮件发送功能,但一直未解决阿里云邮件推送问题,提交工单一开始的回复不尽如人意,比如您的网络问题,您的用户名密码不正确等,但继续沟通下阿里云客户还 ...
- node.js中使用socket.io + express进行实时消息推送
socket.io是一个websocket库,包含客户端的js和服务端的node.js,可以在不同浏览器和移动设备上构建实时应用. 一.安装 socket.io npm install socket. ...
- 浅议Grpc传输机制和WCF中的回调机制的代码迁移
浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...
- WCF初探-23:WCF中使用Message类(下)
前言 在上一篇WCF中使用Message类(上)中,文章介绍了WCF中使用Message类的基本知识和怎样创建消息,本文是承接上一篇文章,如果想要更好的阅读本文,请先阅读上一篇文章.在这篇文章中,我将 ...
- Android、iOS和Windows Phone中的推送技术
推送并不是什么新技术,这种技术在互联网时代就已经很流行了.只是随着进入移动互联网时代,推送技术显得更加重要.因为在智能手机中,推送从某种程度上,可以取代使用多年的短信,而且与短信相比,还可以向用户展示 ...
- APNS IOS 消息推送沙盒模式和发布模式
在做.NET向IOS设备的App进行消息推送时候,采用的是PushSharp开源类库进行消息的推送,而在开发过程中,采用的是测试版本的app,使用的是测试的p12证书采用的是ApnsConfigura ...
随机推荐
- Maven编译的时候加载本地路径jar
大家都知道Maven的依赖是通过pom文件管理的,只要配置了<dependency>,Maven就会从本地仓库 -> 远程仓库 -> 中央仓库获取依赖的jar. 但是如果仓库中 ...
- 【yum】yum的使用
Yum官网 Yum的缓存 Yum仓库 Yum命令 Yum插件 yum的缓存 通过缓存可以提升我们环境的搭建效率,直接把原来缓存好的安装包数据放到新环境,省去了几个G的下载,甚至,有些时候客户现场不能联 ...
- springboot logback + log4j2日志管理
springboot的web项目中自带了日志组件: 我们看一下,springboot中找到日志组件. <dependency> <groupId>org.springframe ...
- Thinking in java note1
Part information collecting from http://blog.csdn.net/leonliu06/article/details/78638841 1. 如果已经定义了一 ...
- git 撤销
在add之前撤回文件: git checkout src/com/jay/example/testforgit/MainActivity.java 已经add的,先取消添加,再撤回 git reset ...
- Java的System.out.println()的解析
Java的System.out.println()的解析 System 是java.lang中的一个类. System.out 中的out, 代表了System类中的静态对象PrintStream, ...
- 【SQL Server高可用性】数据库复制:SQL Server 2008R2中数据库复制
经常在论坛中看到有人问数据同步的技术,如果只是同步少量的表,那么可以考虑使用链接服务器+触发器,来实现数据同步,但当要同步的数据表比较多,那么可以考虑用数据库复制技术,来实现数据的同步. 一.使用场景 ...
- 雷林鹏分享:JSP 简介
JSP 简介 什么是Java Server Pages? JSP全称Java Server Pages,是一种动态网页开发技术.它使用JSP标签在HTML网页中插入Java代码.标签通常以<%开 ...
- HTMLElement.hidden; CSS Attr Selectors的用处; DOM的className方法; ::before和::after伪元素
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/hidden https://codepen.io/pen/ <elem ...
- php--------网页开发实现微信JS的(定位,地图显示,照片选择功能)
今天说说微信网页开发中一下JS的功能,分享一下,希望对各位有所帮助. 前提:要有公众号,和通过微信认证,绑定域名,得到相应信息,appid,appsecret等. 微信开发文档:https://mp. ...