完成的效果图:

服务器端代码:

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. c++对象创建带括号与无括号的区别

    class Test{public: Test() {} Test(int a) {}} 1.栈上创建对象 1.1 无括号 Test a; // 调用默认构造函数,栈上分配内存创建对象 1.2 有括号 ...

  2. 35 网络相关函数(三)——live555源码阅读(四)网络

    35 网络相关函数(三)——live555源码阅读(四)网络 35 网络相关函数(三)——live555源码阅读(四)网络 简介 5)NoReuse不重用地址类 6)initializeWinsock ...

  3. PL/Cool

    毛子 2003 Petrozavodsk, Final Contest, 8.30.03. G. PL/Cool 实现一个程序,使它读入一段PL/Cool程序,并输出它的结果. PL/Cool语法 b ...

  4. MySql 导出excel

    select * into outfile './bestlovesky.xls' from bestlovesky where 1 order by id desc  limit 0, 50;

  5. HTK学习1:安装编译

    选自:http://www.cnblogs.com/mingzhao810/archive/2012/08/03/2617674.html HTK(HMM Toolkit)一款基于hmm模型的语音处理 ...

  6. Linux内核 TCP/IP、Socket参数调优

    Linux内核 TCP/IP.Socket参数调优 2014-06-06  Harrison....   阅 9611  转 165 转藏到我的图书馆   微信分享:   Doc1: /proc/sy ...

  7. 使用Axis2编写webservice客户端,服务端

    1.编写客户端 Axis2开发WebService客户端 的3种方式 [参考帖子] http://blog.csdn.net/wangjinwei6912/article/details/851259 ...

  8. PHP生命周期

    2015-08-19 15:05:30 周三 一篇很好的文章 PHP内核探索 总结一下 1. 模块初始化 MINIT 各个PHP模块/扩展初始化内部变量, 告诉PHP调用自己的函数时, 函数体在哪里( ...

  9. 添加或修改ssh服务的端口

    通常ssh远程登录的默认端口是22,这个端口一般是可以更改或者添加的,配置文件位置在:/etc/ssh/sshd_config通过编辑文件可以修改sshd服务的相关配置,以下新增端口2223,即除了2 ...

  10. Java for LeetCode 234 Palindrome Linked List

    解题思路: O(1)的空间复杂度,意味着不能通过开一个List来解决问题.我们可以把List分成前后两个部分,后半部分通过指针的相互赋值进行翻转即可. JAVA实现如下: public static ...