本篇完成 4.1 所述聊天系统基本功能部分
 
先看下使用截图
 
 
通过菜单中的 file ,load 登录,需输入名字
主界面左侧为当前在线角色列表
右侧上方为当前所有聊天信息集
右侧下方为聊天信息输入窗口(暂且挂钩广播聊天)
 
 
工程结构描述
 
ChatProtocal 聊天协议
ChatService  服务实现
ChatHost 服务宿主(console 程序)
ChatClient 客户端(winform 程序)
 
 
涉及到的类型
 
IChatService 服务契约
IChatServiceCallback 服务回调契约
User 角色信息体
ChatService 服务实现
UserManager 用户管理
ChaterForm 回调协议实现
 
 
关键代码段
InBlock.gif聊天协议,需会话状态存储用户信息,开启重入防止死锁
InBlock.gif
InBlock.gif        [ServiceContract(Namespace = "szgamer",
InBlock.gif                Name = "ChatService",    
InBlock.gif                SessionMode = SessionMode.Required,    
InBlock.gif                ProtectionLevel = ProtectionLevel.None,
InBlock.gif                CallbackContract=typeof(IChatServiceCallback))]
InBlock.gif        public interface IChatService
InBlock.gif        {
InBlock.gif                [OperationContract(Name="Enter",IsOneWay=true)]
InBlock.gif                void Enter(string name);
InBlock.gif                [OperationContract(Name = "Exit", IsOneWay = true)]
InBlock.gif                void Exit();
InBlock.gif                [OperationContract(Name = "BroadcastChat", IsOneWay = true)]
InBlock.gif                void BroadcastChat(string content);
InBlock.gif                [OperationContract(Name = "PrivateChat", IsOneWay = true)]
InBlock.gif                void PrivateChat(string target, string content);
InBlock.gif        }
InBlock.gif
InBlock.gif聊天回调协议
InBlock.gif
InBlock.gif        public interface IChatServiceCallback
InBlock.gif        {
InBlock.gif                [OperationContract(Name = "BroadcastChated", IsOneWay = true)]
InBlock.gif                void BroadcastChated(User who, string content);
InBlock.gif                [OperationContract(Name = "PrivateChated", IsOneWay = true)]
InBlock.gif                void PrivateChated(User who, string content);
InBlock.gif                [OperationContract(Name = "NotifyUserList", IsOneWay = true)]
InBlock.gif                void NotifyUserList(IList<User> users);
InBlock.gif        }
InBlock.gif
InBlock.gif用户信息体,只公开运行时标识和名字给客户端
InBlock.gif
InBlock.gif        [DataContract(Namespace = "szgamer", Name = "User")]
InBlock.gif        public class User : IExtensibleDataObject
InBlock.gif        {
InBlock.gif                [DataMember(Name = "Rtid", IsRequired = true, Order = 0)]
InBlock.gif                public string Rtid
InBlock.gif                {
InBlock.gif                        get;
InBlock.gif                        set;
InBlock.gif                }
InBlock.gif                [DataMember(Name = "Name", IsRequired = true, Order = 1)]
InBlock.gif                public string Name
InBlock.gif                {
InBlock.gif                        get;
InBlock.gif                        set;
InBlock.gif                }
InBlock.gif
InBlock.gif                public ExtensionDataObject ExtensionData
InBlock.gif                {
InBlock.gif                        get;
InBlock.gif                        set;
InBlock.gif                }
InBlock.gif
InBlock.gif                public IChatServiceCallback Callback
InBlock.gif                {
InBlock.gif                        get;
InBlock.gif                        set;
InBlock.gif                }
InBlock.gif
InBlock.gif                public User(string rtid, string name, IChatServiceCallback callback)
InBlock.gif                {
InBlock.gif                        Rtid = rtid;
InBlock.gif                        Name = name;
InBlock.gif                        Callback = callback;
InBlock.gif                }
InBlock.gif
InBlock.gif                public override string ToString()
InBlock.gif                {
InBlock.gif                        return string.Format("{0}: {1}", Name, Rtid);
InBlock.gif                }
InBlock.gif        }
InBlock.gif
 
InBlock.gif用户管理部分,使用需考虑线程安全
InBlock.gif
InBlock.gif        public class UserManager
InBlock.gif        {
InBlock.gif                List<User> _UserList = new List<User>();
InBlock.gif
InBlock.gif                public IList<User> UserList
InBlock.gif                {
InBlock.gif                        get { return _UserList; }
InBlock.gif                }
InBlock.gif
InBlock.gif                object _SyncRoot = new object();
InBlock.gif                public object SyncRoot
InBlock.gif                {
InBlock.gif                        get { return _SyncRoot; }
InBlock.gif                }
InBlock.gif
InBlock.gif                public event Action UserListChanged;
InBlock.gif
InBlock.gif                void RaiseUserListChanged()
InBlock.gif                {
InBlock.gif                        var h = UserListChanged;
InBlock.gif                        if (h != null)
InBlock.gif                        {
InBlock.gif                                h();
InBlock.gif                        }
InBlock.gif                }
InBlock.gif
InBlock.gif                public void AddUser(User user)
InBlock.gif                {
InBlock.gif                        _UserList.Add(user);
InBlock.gif
InBlock.gif                        RaiseUserListChanged();
InBlock.gif                }
InBlock.gif
InBlock.gif                public void Remove(string user)
InBlock.gif                {
InBlock.gif                        foreach (var i in _UserList)
InBlock.gif                        {
InBlock.gif                                if (i.Rtid == user)
InBlock.gif                                {
InBlock.gif                                        _UserList.Remove(i);
InBlock.gif                                        RaiseUserListChanged();
InBlock.gif                                        return;
InBlock.gif                                }
InBlock.gif                        }
InBlock.gif                }
InBlock.gif
InBlock.gif                public bool Contains(string user)
InBlock.gif                {
InBlock.gif                        return GetUser(user) != null;
InBlock.gif                }
InBlock.gif
InBlock.gif                public User GetUser(string user)
InBlock.gif                {
InBlock.gif                        foreach (var i in _UserList)
InBlock.gif                        {
InBlock.gif                                if (i.Rtid == user)
InBlock.gif                                {
InBlock.gif                                        return i;
InBlock.gif                                }
InBlock.gif                        }
InBlock.gif
InBlock.gif                        return null;
InBlock.gif                }
InBlock.gif        }
InBlock.gif
InBlock.gif
InBlock.gif聊天信息广播
InBlock.gif
InBlock.gif                public void BroadcastChat(string content)
InBlock.gif                {
InBlock.gif                        lock (_UserManager.SyncRoot)
InBlock.gif                        {
InBlock.gif                                var user = _UserManager.GetUser(SessionId);
InBlock.gif                                if (user == null)
InBlock.gif                                        return;
InBlock.gif                                Console.WriteLine(string.Format("[BroadcastChat] {`0`} {1}", user.ToString(), content));
InBlock.gif
InBlock.gif                                foreach (var i in _UserManager.UserList)
InBlock.gif                                {
InBlock.gif                                        i.Callback.BroadcastChated(user, content);
InBlock.gif                                }
InBlock.gif                        }
InBlock.gif                }
InBlock.gif
InBlock.gif
InBlock.giftcp 绑定,忽略安全
InBlock.gif
InBlock.gif                <bindings>
InBlock.gif                        <netTcpBinding>
InBlock.gif                                <binding name="tcpBinding">
InBlock.gif                                        <security mode="None">
InBlock.gif                                        </security>
InBlock.gif                                </binding>
InBlock.gif                        </netTcpBinding>
InBlock.gif                </bindings>
InBlock.gif