重温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("宋体"), 12,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之群聊天程序(十)

时间: 2024-10-29 06:51:43

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

JAVA学习第六十课 — UDP协议 &amp;基于多线程模拟简单的QQ聊天程序

UDP传输 UDP有发送端和接受端,有两大类,DatagramSocket.DatagramPacket 建立发送端和接收端 建立数据包 调用Socket的接收发送方法 关闭Socket 注意:发送端和接收端是两个独立的运行程序 UDP发送端演示 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号. public static voi

Socket聊天程序——初始设计

写在前面: 可能是临近期末了,各种课程设计接踵而来,最近在csdn上看到2个一样问答(问题A,问题B),那就是编写一个基于socket的聊天程序,正好最近刚用socket做了一些事,出于兴趣,自己抽了几个晚上的空闲时间敲了一个,目前仅支持单聊,群聊,文件传送这些功能.首先,贴出一个丑丑的程序图(UI是用java swing写的,这个早就忘光了,无奈看着JDK的API写了一个),如下图: 服务端设计: 服务端主要有两个操作,一是阻塞接收客户端的socket并做响应处理,二是检测客户端的心跳,如果客

java Socket多线程聊天程序(适合初学者)

一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者 下面是服务器端代码 package tk.socket; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.Act

重温WCF之消息拦截与篡改(八)

我们知道,在WCF中,客户端对服务操作方法的每一次调用,都可以被看作是一条消息,而且,可能我们还会有一个疑问:如何知道客户端与服务器通讯过程中,期间发送和接收的SOAP是什么样子.当然,也有人是通过借助其他工具来抓取数据包来查看.那,有没有办法让程序自己输出相应的SOAP信息呢? 要对SOAP消息进行拦截和修改,我们需要实现两个接口,它们都位于System.ServiceModel.Dispatcher (程序集System.ServiceModel).下面分别价绍. 接口一:IClientMe

手把手教你搭建LyncServer2013之体验持久聊天室(十四)

上一节,我们完成了持久聊天服务器的搭建,下面我们开始体验Lync Server 2013的新功能了,个人感觉非常的不错!首先,我们需要创建一个类别,点击"新建"按钮 点击选择我们的持久聊天服务器池,然后点击"确定" 输入类别名称和说明,然后勾选启用邀请.启用文件上载,启用聊天历史记录,然后在允许的成员栏中,点击添加按钮添加允许成员 在创建者中添加可以创建聊天室的成员,完成后点击"提交"完成类别的添加 切换到聊天室策略,勾选"启用持久聊天

从一个简单的聊天程序SimpleChat看VPN技术

SimpleVPN写好了以后,感觉比较简单,我觉得只有简单的东西才经得起折腾,才能全民折腾,所以说SimpleVPN还不够简单,本文来一个更加简单的,展示一个超级简单的点对点聊天程序,而且还带简单加密哦.顺便,我们再来看下,到底什么是VPN以及怎样实现它.       QQ如今才刚刚行过成年之礼,典型的90后00前,却早已到了后浪把前浪拍到岸边的砍儿,果不其然,被10后的微信给逆袭了...好在都是腾讯的,这就把竞争收敛到了公司内部,不然这将意味着一个巨人的倒下,太可怕了.多年前,很多人逆向过QQ

Java网络编程以及简单的聊天程序

网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编程简要概述: 网络编程实质实质就是两个(或多个)设备(例如计算机)之间的数据传输.而要实现两台计算机通过互联网连接进行数据传输,必输要满足计算机网络的5层协议(物理层,数据链路层,网络层,运输层,应用层):当然有划分可能不同,但现在大家比较容易接受理解的是五层模型.而其中前三层物理层,数据链路层以及

Socket网络编程--聊天程序(9)

这一节应该是聊天程序的最后一节了,现在回顾我们的聊天程序,看起来还有很多功能没有实现,但是不管怎么说,都还是不错的.这一节我们将讲多服务器问题(高大上的说法就是负载问题了.)至于聊天程序的文件发送(也即二进制文件发送例如图片)和单点登陆(就是多加一个数组fd_L[],用来记录是否已经登陆过了.),这些问题就不讨论了. 支持多服务器实现负载问题的聊天程序 今天才知道原来我们一直使用的select来处理IO多路复用的这个函数最多只能有1024个连接,因为内部实现里面的数组就是只有1024,多了不行.

Socket网络编程--聊天程序(8)

上一节已经完成了对用户的身份验证了,既然有了验证,那么接下来就能对不同的客户端进行区分了,所以这一节讲实现私聊功能.就是通过服务器对客户端的数据进行转发到特定的用户上, 实现私聊功能的聊天程序 实现的技术细节是:对客户端发送的数据增加一个标识头,由于我们处理的是纯文本,所以为了讲解的方便就把标识头加到聊天信息的前面,然后在服务器中判断.如果是要在做成产品的话,因为要考虑传送纯文本,图片,文件,特定的结构体等等其他非纯文本信息,那么我们可以对一次聊天信息,发送两次数据,第一次用TCP发送一个结构体