完成的效果图:

服务器端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks; namespace SendMessageHostConsoleApplication
{
[ServiceContract(SessionMode=SessionMode.Required,CallbackContract=typeof(ICallback))]
public interface IService
{
/// <summary>
/// 启动会话
/// </summary>
[OperationContract(IsOneWay=true,IsInitiating=true,IsTerminating=false)]
void Begin(); /// <summary>
/// 客户端调用服务器端发送消息
/// </summary>
/// <param name="nick"></param>
/// <param name="msg"></param>
/// <param name="sendTime"></param>
[OperationContract(IsOneWay = true)]
void SendMessage(string nick,string msg,DateTime sendTime); /// <summary>
/// 终止会话
/// </summary>
[OperationContract(IsOneWay=true,IsInitiating=false,IsTerminating=true)]
void End(); } public interface ICallback
{
/// <summary>
/// 服务器端调用客户端发送消息
/// </summary>
/// <param name="nick"></param>
/// <param name="msg"></param>
/// <param name="sendTime"></param>
[OperationContract(IsOneWay=true)]
void SendToClients(string nick,string msg,DateTime sendTime);
} [ServiceBehavior(IncludeExceptionDetailInFaults=true,InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService : IService
{
public static Dictionary<string, ICallback> ClientCallBacks = new Dictionary<string, ICallback>();
public void Begin()
{
string sessionId = OperationContext.Current.SessionId;
ICallback cb = OperationContext.Current.GetCallbackChannel<ICallback>();
MyService.ClientCallBacks[sessionId] = cb;
} public void SendMessage(string nick, string msg, DateTime sendTime)
{
foreach (ICallback c in MyService.ClientCallBacks.Values)
{
if (c != null)
{
c.SendToClients(nick, msg, sendTime);
}
}
} public void End()
{
string sessionId = OperationContext.Current.SessionId;
if (MyService.ClientCallBacks.ContainsKey(sessionId))
{
MyService.ClientCallBacks.Remove(sessionId);
}
}
}
public class Program
{
public static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(MyService)))
{
NetTcpBinding bingding = new NetTcpBinding();
bingding.Security.Mode = SecurityMode.None;//不需要安全模式
host.AddServiceEndpoint(typeof(IService), bingding, "net.tcp://127.0.0.1:8868/channel"); ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;
behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/WSDL"); //httpGetUrl客户端引用的地址
host.Description.Behaviors.Add(behavior);
host.Opened += delegate
{
Console.WriteLine("服务已启动");
Console.ReadKey();
};
host.Open();
}
}
}
}

客户端调用代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms; namespace SendMessageClientWindowsFormsApplication
{ public partial class Form1 : Form
{
private WS.ServiceClient client = null;
public Form1()
{
InitializeComponent();
MyCallback callback = new MyCallback();
callback.MessageReceived += callback_MessageReceived;
var instanceContext = new InstanceContext(callback);
client = new WS.ServiceClient(instanceContext);
client.Begin();
this.FormClosed += Form1_FormClosed;
} void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
client.End();
} private void btnSend_Click(object sender, EventArgs e)
{ client.SendMessage(this.txtNick.Text, this.txtSendMsg.Text, DateTime.Now);
} void callback_MessageReceived(object sender, CallbackRecEventArgs e)
{
ListViewItem item = new ListViewItem();
Font font = new System.Drawing.Font(new FontFamily("宋体"), ,FontStyle.Bold);
item.Font = font;
item.ForeColor = Color.Blue;
if (e.Nick == this.txtNick.Text)
{
item.ForeColor = Color.Green;
}
item.Text = e.Nick + " " + e.SendTime+"\r\n";
listView1.Items.Add(item);
listView1.Items.Add(e.Message);
this.txtSendMsg.Text = "";
}
} public class MyCallback : WS.IServiceCallback
{
public void SendToClients(string nick, string msg, DateTime sendTime)
{
if (this.MessageReceived != null)
{
CallbackRecEventArgs arg = new CallbackRecEventArgs(nick, msg, sendTime);
this.MessageReceived(this, arg);
}
} public event EventHandler<CallbackRecEventArgs> MessageReceived;
} public class CallbackRecEventArgs : EventArgs
{
private string _Nick, _Msg;
private DateTime _time; public CallbackRecEventArgs(string nk, string m, DateTime t)
{
_Nick = nk;
_Msg = m;
_time = t;
} public string Nick
{
get { return _Nick; }
} public string Message
{
get { return _Msg; }
} public DateTime SendTime
{
get { return _time; }
}
} }

重温WCF之群聊天程序(十)的更多相关文章

  1. Socket聊天程序——初始设计

    写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答(问题A,问题B),那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了 ...

  2. Comet实现的网页聊天程序

    “上一篇”介绍了我在c/s程序中用了那些技术,如今只谈c/s不谈b/s那未免out了,势必要写一写b/s的程序与大家共勉. 回忆做技术这些年,06年每天盯着“天轰穿”的视频不亦乐乎,估计那是一代程序员 ...

  3. WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]

    原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...

  4. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...

  5. WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]

    原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...

  6. WCF技术剖析之二十: 服务在WCF体系中是如何被描述的?

    原文:WCF技术剖析之二十: 服务在WCF体系中是如何被描述的? 任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源.同理,一个WCF服务的监听与执行同样需要通过 ...

  7. Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程

    设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...

  8. 基于UDP协议的控制台聊天程序(c++版)

    本博客由Rcchio原创,转载请告知作者 ------------------------------------------------------------------------------- ...

  9. java Socket多线程聊天程序

    参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...

随机推荐

  1. 基于Selenium的模拟浏览器采集

    Selenium 也是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7.8.9).Mozilla Firefox.Mozil ...

  2. Js 的 this 是什么

    this指的是调用函数的那个对象,谁调用函数,谁就是this 更多: http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_thi ...

  3. 【Nginx】nginx 代理 Haproxy 怎么设置?

    由于Haproxy是通过 url 正则匹配 识别 的,nginx代理到 haproxy需要设置 proxy_set_header Host 为 haproxy的目标 url 直接上配置 upstrea ...

  4. SqlServer中的Null值空值问题

    sql使用的是三值谓词逻辑,所以逻辑表达式返回的结果可以为True.False或者未知,在三值逻辑中返回True与不返回False并不完全一样, SQL对查询过滤条件的处理:接受TURE  拒绝FAL ...

  5. Ubuntu里面软件的安装与卸载

    在Ubuntu里面,有时候碰到软件配置错了,这是重新再安装的话,会检测到已安装,系统不会再重新安装,就需要卸载之后重装 1.通过deb包安装的情况: 安装.deb包: 代码:sudo dpkg -i ...

  6. 修改MySQL中字段的类型和长度

    MySQL修改字段类型的命令是: mysql> alter table 表名 modify column 字段名 类型; 假设在MySQL中有一个表为:address,有一个字段为city 初始 ...

  7. TS初探

    简介 TypeScript具有类型系统,且是JavaScript的超集.它可以编译成普通的JavaScript代码. TypeScript支持任意浏览器,任意环境,任意系统并且是开源的.Ts主要用于解 ...

  8. Python 开发轻量级爬虫04

    Python 开发轻量级爬虫 (imooc总结04--url管理器) 介绍抓取URL管理器 url管理器用来管理待抓取url集合和已抓取url集合. 这里有一个问题,遇到一个url,我们就抓取它的内容 ...

  9. QT Creator调用动态链接库实例

    #include<iostream> #include <QLibrary> using namespace std; int main() { cout<<&qu ...

  10. 【EM】代码理解

    本来想自己写一个EM算法的,但是操作没两步就进行不下去了.对那些数学公式着实不懂.只好从网上找找代码,看看别人是怎么做的. 代码:来自http://blog.sina.com.cn/s/blog_98 ...