完善事件框架

This commit is contained in:
Mattuy
2018-12-15 17:54:19 +08:00
parent 145c242d4b
commit 0e6d1922e0
10 changed files with 124 additions and 40 deletions
@@ -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";
}
}
+44 -3
View File
@@ -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);
/// <summary>
/// 与服务器进行数据通信,并向外部提供一系列通信接口
/// </summary>
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<Packet>();
}
/// <summary>
/// 初始化客户端,连接服务器。如果成功则启动数据接收和发送线程
/// </summary>
@@ -62,7 +103,7 @@ namespace Interact
}
/// <summary>
/// 登录。此操作为异步操作,完成后产生OnLoginDone事件。
/// 登录。此操作为异步操作,服务器返回结果后产生OnLoginDone事件。
/// </summary>
/// <returns>成功将请求加入发送队列返回true,否则返回false。</returns>
/// <param name="user">用户名</param>
+30 -7
View File
@@ -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<User>(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);
}
}
}
+2 -1
View File
@@ -36,6 +36,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -55,7 +56,7 @@
</Compile>
<Compile Include="Read.cs" />
<Compile Include="Send.cs" />
<Compile Include="Strings.cs" />
<Compile Include="AttrNames.cs" />
<Compile Include="User.cs" />
</ItemGroup>
<ItemGroup>
+27 -2
View File
@@ -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
}
+8 -19
View File
@@ -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; }
}
//从服务器接收的原始数据封包
Binary file not shown.