重温WCF之群聊天程序(十)
完成的效果图:

服务器端代码:
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之群聊天程序(十)的更多相关文章
- Socket聊天程序——初始设计
写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答(问题A,问题B),那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了 ...
- Comet实现的网页聊天程序
“上一篇”介绍了我在c/s程序中用了那些技术,如今只谈c/s不谈b/s那未免out了,势必要写一写b/s的程序与大家共勉. 回忆做技术这些年,06年每天盯着“天轰穿”的视频不亦乐乎,估计那是一代程序员 ...
- WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]
原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-ME ...
- WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]
原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...
- WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]
原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...
- WCF技术剖析之二十: 服务在WCF体系中是如何被描述的?
原文:WCF技术剖析之二十: 服务在WCF体系中是如何被描述的? 任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源.同理,一个WCF服务的监听与执行同样需要通过 ...
- Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程
设备控制软件编程涉及到的基本通信方式主要有TCP/IP与串口,用到的数据通信协议有Fins与ModBus. 更高级别的通信如.net中的Remoting与WCF在进行C/S架构软件开发时会采用. 本篇 ...
- 基于UDP协议的控制台聊天程序(c++版)
本博客由Rcchio原创,转载请告知作者 ------------------------------------------------------------------------------- ...
- java Socket多线程聊天程序
参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...
随机推荐
- OpenCV成长之路 01、图像的读写与显示
一.工具篇 工欲善其事,必先利其器.学习OpenCV,肯定少不于基本的编程工具与OpenCV库.在Windows平台下你可以选择Visual Studio.CodeBlock等,当然你也可以选择在Li ...
- Android活动管理工具
ActivityCollector.java import android.app.Activity; import java.util.ArrayList; import java.util.Lis ...
- Tip
Windows 开栈命令 -Wl,--stack=1000000000 //stack-size B Linux 开栈命令 -ulimit -a -ulimit -s size //stack-siz ...
- 解压.tar.gz出错gzip: stdin: not in gzip format tar: /Child returned status 1 tar: Error is not recoverable: exiting now
先查看文件真正的属性是什么? [root@xxxxx ~]# tar -zxvf tcl8.4.16-src.tar.gz gzip: stdin: not in gzip format tar: ...
- 获取shell脚本自身所在目录的Shell脚本分享
前几天写的七牛的参赛demo,用bash写了一个便捷安装的脚本,涉及到了路径相关的判断,从stackoverflow,加上自己的实践整理一下. 简单版 下面是一个最简单的实现,可以解决大多数问题,缺陷 ...
- linux skill
linux console终端乱码解决 1.console终端乱码 在/etc/profile文件的最后一行添加如下内容: export LC_ALL="zh_CN.GB18030" ...
- 转:C++编程隐蔽错误:error C2533: 构造函数不能有返回类型
C++编程隐蔽错误:error C2533: 构造函数不能有返回类型 今天在编写类的时候,出现的错误. 提示一个类的构造函数不能够有返回类型.在cpp文件里,该构造函数定义处并没有返回类型.在头文件里 ...
- ios iphone6 Plus 的适配问题
最近更新一个老程序,发现在iphone6 plus上用nslog打印出的screen 的frame还是320*568, 不是414*736, 查了一下,原来需要设置iphone6 plus的启动画面才 ...
- ePass.CreateFile
javascript和vbscript中没有结构体Struct,ePass的ActiveX对象中把各个参数都展开了,官方文档只给出了对应的代码,没有给出相应的数字,示例代码中却都是数字,其VC代码中有 ...
- ABAP 内表的行列转换-发货通知单-打印到Excel里
需要传入数据到Excel里的模板如上图所示 ********************** * 设计主要逻辑与原理说明 ...