diff --git a/.gitignore b/.gitignore index 75419e8..f475183 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ # Binaries for programs and plugins *.exe *.exe~ -*.dll +#*.dll *.so *.dylib diff --git a/Interact/Strings.cs b/Interact/AttrNames.cs similarity index 51% rename from Interact/Strings.cs rename to Interact/AttrNames.cs index 508a169..a780338 100644 --- a/Interact/Strings.cs +++ b/Interact/AttrNames.cs @@ -5,11 +5,16 @@ using System.Text; namespace Interact { - //字符串常量 - public static class Strings + //Json数据的字段访问字符串 + public static class AttrNames { public const string Token = "Token"; public const string Operation = "Operation"; public const string Error = "Error"; + + public const string User = "User"; + public const string NickName = "NickName"; + public const string Motto = "Motto"; + public const string UGroup = "UGroup"; } } diff --git a/Interact/Client.cs b/Interact/Client.cs index 5b324cf..c995f73 100644 --- a/Interact/Client.cs +++ b/Interact/Client.cs @@ -6,21 +6,59 @@ using System.Net.Sockets; using System.Net; using System.Threading; using System.Collections.Concurrent; -using Newtonsoft.Json.Linq; +using System.Drawing; namespace Interact { //连接中断 public delegate void DisconnectHandler(Exception ex); + //通用请求结果处理 + public delegate void ResultHandler(ResultHead head); + //消息到达事件处理 + public delegate void MessageHandler(Message msg); //登录反馈到达 - public delegate void LoginDoneHandler(JObject head, User user); + public delegate void LoginDoneHandler(ResultHead head, User user); + //获取用户列表结果处理 + public delegate void GetUserListDoneHandler(ResultHead head, User[] users); + //获取用户头像结果处理 + public delegate void GetUserPhotoDoneHandler(ResultHead head, Image image); + + /// + /// 与服务器进行数据通信,并向外部提供一系列通信接口 + /// public static partial class StormClient { //连接中断事件 public static event DisconnectHandler OnDisconnect; + //服务器异常消息处理事件 + public static event ResultHandler OnPanic; + //服务器强制注销登陆事件 + public static event ResultHandler OnOffline; + //消息到达事件 + public static event MessageHandler OnMessage; + //发送消息处理完成反馈事件(仅在DoesSendMessageReturn为true时有效) + public static event ResultHandler OnSendMessageDone; + //更新用户信息结果处理事件 + public static event ResultHandler OnUpdateUserInfoDone; //登录结果处理事件 public static event LoginDoneHandler OnLoginDone; + //获取用户列表结果处理事件 + public static event GetUserListDoneHandler OnGetUserListDone; + //获取用户头像结果处理事件 + public static event GetUserPhotoDoneHandler OnGetUserPhotoDoneHandler; + //发送消息时是否要求服务器返回处理结果 + public static bool DoesSendMessageReturn + { + get + { + return doesSendMessageReturn != 0; + } + set + { + Interlocked.Exchange(ref StormClient.doesSendMessageReturn, value ? 1 : 0); + } + } //TCP客户端 private static TcpClient tcpClient; @@ -30,12 +68,15 @@ namespace Interact private static Thread readLoopThread; //数据发送线程 private static Thread sendLoopThread; + //发送消息时是否要求服务器返回处理结果 + private static volatile int doesSendMessageReturn = 0; static StormClient() { tcpClient = new TcpClient(); sendQueue = new BlockingCollection(); } + /// /// 初始化客户端,连接服务器。如果成功则启动数据接收和发送线程 /// @@ -62,7 +103,7 @@ namespace Interact } /// - /// 登录。此操作为异步操作,完成后产生OnLoginDone事件。 + /// 登录。此操作为异步操作,服务器返回结果后产生OnLoginDone事件。 /// /// 成功将请求加入发送队列返回true,否则返回false。 /// 用户名 diff --git a/Interact/Handle.cs b/Interact/Handle.cs index 1bb74c6..ec30600 100644 --- a/Interact/Handle.cs +++ b/Interact/Handle.cs @@ -14,10 +14,10 @@ namespace Interact { string head = Encoding.UTF8.GetString(headData); JObject jsonObj = (JObject)JsonConvert.DeserializeObject(head); - switch ((Operations)Enum.Parse(typeof(Operations), jsonObj[Strings.Operation].ToString())) + switch ((Operations)Enum.Parse(typeof(Operations), jsonObj[AttrNames.Operation].ToString())) { case Operations.Login: - HandleLoginResult(jsonObj, data); + HandleLoginResult(GetResultHead(jsonObj), data); break; case Operations.Panic: case Operations.TransMessage: @@ -32,14 +32,37 @@ namespace Interact break; } } - //处理登录反馈消息 - private static void HandleLoginResult(JObject head, byte[] data) + + //提取基本结果包头结构 + private static ResultHead GetResultHead(JObject head) { - User user = null; - if (head[Strings.Error].ToString() == "") - user = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(data)) as User; + ResultHead resultHead = new ResultHead + { + Token = head[AttrNames.Token].ToString(), + Operation = head[AttrNames.Operation].ToString(), + Error = head[AttrNames.Error].ToString() + }; + return resultHead; + } + + //处理登录反馈消息 + private static void HandleLoginResult(ResultHead head, byte[] data) + { + //发起登录完成事件 + if (head.Error != "") + OnLoginDone?.Invoke(head, null); + JObject dataObj = (JObject)JsonConvert.SerializeObject(data); + User user = new User + { + Name = dataObj[AttrNames.User].ToString(), + NickName = dataObj[AttrNames.NickName].ToString(), + Motto = dataObj[AttrNames.Motto].ToString(), + Group = (UserGroup)Enum.Parse(typeof(UserGroup), dataObj[AttrNames.UGroup].ToString()) + }; OnLoginDone?.Invoke(head, user); } + + } } diff --git a/Interact/Interact.csproj b/Interact/Interact.csproj index 7582ed8..331e988 100644 --- a/Interact/Interact.csproj +++ b/Interact/Interact.csproj @@ -36,6 +36,7 @@ + @@ -55,7 +56,7 @@ - + diff --git a/Interact/JsonObject.cs b/Interact/JsonObject.cs index 8498d7e..fd2ef53 100644 --- a/Interact/JsonObject.cs +++ b/Interact/JsonObject.cs @@ -3,10 +3,26 @@ using System.Collections.Generic; using System.Linq; using System.Text; -//此文件定义Json序列化与反序列化时使用的数据结构,仅内部使用 - namespace Interact { + #region 定义数据交互用到的数据结构(可能作为事件或回调函数的参数) + //包头基本结构 + public class BaseHead + { + //请求ID,由发送方定义的随机字符串。如果接受方有返回数据应包含相同的Token + public string Token; + //操作类型,决定数据的其他内容 + public string Operation; + } + // 接受方返回的执行结果反馈包头,包含错误文本 + public class ResultHead : BaseHead + { + //错误文本,为空则执行成功 + public string Error; + } + #endregion + + #region 定义Json序列化与反序列化时使用的数据结构,仅内部使用 //登录信息包头 internal class JsonLogInfoHead : BaseHead { @@ -14,4 +30,13 @@ namespace Interact public string Pwd; } + //用户信息 + internal class JsonUserInfo + { + public string User; //用户名 + public string NickName; //昵称 + public string Motto; //个性签名 + public string UGroup; //用户组 + } + #endregion } diff --git a/Interact/Message.cs b/Interact/Message.cs index 664320f..1ea5db5 100644 --- a/Interact/Message.cs +++ b/Interact/Message.cs @@ -6,30 +6,19 @@ using System.Threading.Tasks; namespace Interact { - //定义一则用户消息 + //定义一则用户接收到的消息 public class Message { - public static UInt32 MaxHeadLength; //最大包头长度 - public static UInt32 MaxMessageLength; //最大消息长度 - + /*保留 + public const UInt32 MaxHeadLength = 4096; //最大包头长度 + public const UInt32 MaxMessageLength = 0x6400000; //最大数据长度 + */ public DateTime When { get; } //服务器接收时间 public User From; //发送者 public string Content; //消息内容 - } - - //包头基本结构 - public class BaseHead - { - //请求ID,由发送方定义的随机字符串。如果接受方有返回数据应包含相同的Token - public string Token; - //操作类型,决定数据的其他内容 - public string Operation; - } - // 接受方返回的执行结果反馈包头,包含错误文本 - public class ResultHead : BaseHead - { - //错误文本,为空则执行成功 - public string Error; + + //将消息保存到数据库(保留) + protected bool Save() { return false; } } //从服务器接收的原始数据封包 diff --git a/Interact/Newtonsoft.Json.dll b/Interact/Newtonsoft.Json.dll new file mode 100644 index 0000000..5b3a1eb Binary files /dev/null and b/Interact/Newtonsoft.Json.dll differ diff --git a/StormChat/LogForm.cs b/StormChat/LogForm.cs index c00319b..7b99280 100644 --- a/StormChat/LogForm.cs +++ b/StormChat/LogForm.cs @@ -36,16 +36,17 @@ namespace StormChat } //登录结果处理 - private void LoginDone(JObject head, User user) + private void LoginDone(ResultHead head, User user) { Action f = delegate () { btnLogin.Enabled = true; - if (head[Strings.Error].ToString() != "") + if (head.Error != "") { - MessageBox.Show("登录失败:" + head[Strings.Error].ToString()); + MessageBox.Show("登录失败:" + head.Error); return; } + User.Me = user; _mainForm.Opacity = 1; _mainForm.Show(); this.Close(); diff --git a/StormChat/StormChat.csproj b/StormChat/StormChat.csproj index 84e4023..8931dc1 100644 --- a/StormChat/StormChat.csproj +++ b/StormChat/StormChat.csproj @@ -44,8 +44,7 @@ Properties\app.manifest - - False + ..\Interact\Newtonsoft.Json.dll