• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C#教程 > 分享WCF聊天程序--WCFChat实现代码

分享WCF聊天程序--WCFChat实现代码

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了wcf服务应用程序,wcf程序,wcf应用程序,wcf应用程序发布,wcf代码等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

无意中在一个国外的站点下到了一个利用WCF实现聊天的程序,作者是:Nikola Paljetak。研究了一下,自己做了测试和部分修改,感觉还不错,分享给大家。
先来看下运行效果:
开启服务:

客户端程序:


程序分为客户端和服务器端:

------------服务器端:

IChatService.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Collections;

namespace WCFChatService
{
  // SessionMode.Required 允许Session会话。双工协定时的回调协定类型为IChatCallback接口
  [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IChatCallback))]
  public interface IChatService
  {
    [OperationContract(IsOneWay = false, IsInitiating = true, IsTerminating = false)]//----->IsOneWay = false等待服务器完成对方法处理;IsInitiating = true启动Session会话,IsTerminating = false 设置服务器发送回复后不关闭会话
    string[] Join(string name);//用户加入

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void Say(string msg);//群聊信息

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = false)]
    void Whisper(string to, string msg);//私聊信息

    [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
    void Leave();//用户加入
  }
  /// <summary>
  /// 双向通信的回调接口
  /// </summary>
  interface IChatCallback
  {
    [OperationContract(IsOneWay = true)]
    void Receive(string senderName, string message);

    [OperationContract(IsOneWay = true)]
    void ReceiveWhisper(string senderName, string message);

    [OperationContract(IsOneWay = true)]
    void UserEnter(string name);

    [OperationContract(IsOneWay = true)]
    void UserLeave(string name);
  }

  /// <summary>
  /// 设定消息的类型
  /// </summary>
  public enum MessageType { Receive, UserEnter, UserLeave, ReceiveWhisper };
  /// <summary>
  /// 定义一个本例的事件消息类. 创建包含有关事件的其他有用的信息的变量,只要派生自EventArgs即可。
  /// </summary>
  public class ChatEventArgs : EventArgs
  {
    public MessageType msgType;
    public string name;
    public string message;
  }
}
</div>

ChatService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFChatService
{
  // InstanceContextMode.PerSession 服务器为每个客户会话创建一个新的上下文对象。ConcurrencyMode.Multiple 异步的多线程实例
  [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
  public class ChatService : IChatService
  {
    private static Object syncObj = new Object();////定义一个静态对象用于线程部份代码块的锁定,用于lock操作
    IChatCallback callback = null;

    public delegate void ChatEventHandler(object sender, ChatEventArgs e);//定义用于把处理程序赋予给事件的委托。
    public static event ChatEventHandler ChatEvent;//定义事件
    static Dictionary<string, ChatEventHandler> chatters = new Dictionary<string, ChatEventHandler>();//创建一个静态Dictionary(表示键和值)集合(字典),用于记录在线成员,Dictionary<(Of <(TKey, TValue>)>) 泛型类

    private string name;
    private ChatEventHandler myEventHandler = null;


    public string[] Join(string name)
    {
      bool userAdded = false;
      myEventHandler = new ChatEventHandler(MyEventHandler);//将MyEventHandler方法作为参数传递给委托

      lock (syncObj)//线程的同步性,同步访问多个线程的任何变量,利用lock(独占锁),确保数据访问的唯一性。
      {
        if (!chatters.ContainsKey(name) && name != "" && name != null)
        {
          this.name = name;
          chatters.Add(name, MyEventHandler);
          userAdded = true;
        }
      }

      if (userAdded)
      {
        callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();//获取当前操作客户端实例的通道给IChatCallback接口的实例callback,此通道是一个定义为IChatCallback类型的泛类型,通道的类型是事先服务契约协定好的双工机制。
        ChatEventArgs e = new ChatEventArgs();//实例化事件消息类ChatEventArgs
        e.msgType = MessageType.UserEnter;
        e.name = name;
        BroadcastMessage(e);
        ChatEvent += myEventHandler;
        string[] list = new string[chatters.Count]; //以下代码返回当前进入聊天室成员的称列表
        lock (syncObj)
        {
          chatters.Keys.CopyTo(list, 0);//将字典中记录的用户信息复制到数组中返回。
        }
        return list;
      }
      else
      {
        return null;
      }
    }

    public void Say(string msg)
    {
      ChatEventArgs e = new ChatEventArgs();
      e.msgType = MessageType.Receive;
      e.name = this.name;
      e.message = msg;
      BroadcastMessage(e);
    }

    public void Whisper(string to, string msg)
    {
      ChatEventArgs e = new ChatEventArgs();
      e.msgType = MessageType.ReceiveWhisper;
      e.name = this.name;
      e.message = msg;
      try
      {
        ChatEventHandler chatterTo;//创建一个临时委托实例
        lock (syncObj)
        {
          chatterTo = chatters[to]; //查找成员字典中,找到要接收者的委托调用
        }
        chatterTo.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);//异步方式调用接收者的委托调用
      }
      catch (KeyNotFoundException)
      {
      }
    }

    public void Leave()
    {
      if (this.name == null)
        return;

      lock (syncObj)
      {
        chatters.Remove(this.name);
      }
      ChatEvent -= myEventHandler;
      ChatEventArgs e = new ChatEventArgs();
      e.msgType = MessageType.UserLeave;
      e.name = this.name;
      this.name = null;
      BroadcastMessage(e);
    }

    //回调,根据客户端动作通知对应客户端执行对应的操作
    private void MyEventHandler(object sender, ChatEventArgs e)
    {
      try
      {
        switch (e.msgType)
        {
          case MessageType.Receive:
            callback.Receive(e.name, e.message);
            break;
          case MessageType.ReceiveWhisper:
            callback.ReceiveWhisper(e.name, e.message);
            break;
          case MessageType.UserEnter:
            callback.UserEnter(e.name);
            break;
          case MessageType.UserLeave:
            callback.UserLeave(e.name);
            break;
        }
      }
      catch
      {
        Leave();
      }
    }

    private void BroadcastMessage(ChatEventArgs e)
    {

      ChatEventHandler temp = ChatEvent;

      if (temp != null)
      {
        //循环将在线的用户广播信息
        foreach (ChatEventHandler handler in temp.GetInvocationList())
        {
          //异步方式调用多路广播委托的调用列表中的ChatEventHandler 
          handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
        }
      }
    }
    //广播中线程调用完成的回调方法功能:清除异常多路广播委托的调用列表中异常对象(空对象)
    private void EndAsync(IAsyncResult ar)
    {
      ChatEventHandler d = null;

      try
      {
        //封装异步委托上的异步操作结果
        System.Runtime.Remoting.Messaging.AsyncResult asres = (System.Runtime.Remoting.Messaging.AsyncResult)ar;
        d = ((ChatEventHandler)asres.AsyncDelegate);
        d.EndInvoke(ar);
      }
      catch
      {
        ChatEvent -= d;
      }
    }
  }
}
</div>

------------客户端:

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 分享WCF聊天程序--WCFChat实现代码

相关文章

  • 2017-05-28C#简单实现子窗体向父窗体传值的方法
  • 2017-05-28c#中executereader执行查询示例分享
  • 2017-05-28C#中判断本地系统的网络连接状态的方法
  • 2017-05-28WinForm天猫双11自动抢红包源码分享
  • 2017-05-28深入解析C#中的泛型类与泛型接口
  • 2017-05-28C#连接Oracle数据库的方法
  • 2017-05-28C#使用AutoResetEvent实现同步
  • 2017-05-28C#中把日志导出到txt文本的简单实例
  • 2017-05-28C#异步委托调用实例分析
  • 2017-05-28DevExpress TreeList 常见问题解决方法

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 浅谈C#下winform和JS的互相调用和传参(webbrowser)
    • c#中虚函数的相关使用方法
    • C#传值方式实现不同程序窗体间通信实例
    • C#中DataTable 转实体实例详解
    • C#中常见的系统内置委托用法详解
    • DevExpress实现自定义TreeListNode的Tooltip的方法
    • C#面向对象特征的具体实现及作用详解
    • c#生成excel示例sql数据库导出excel
    • 解决C#中WebBrowser的DocumentCompleted事件不执行的实现方法
    • C#通过DataSet读写xml文件的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有