完善事件框架

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
+1 -1
View File
@@ -2,7 +2,7 @@
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe *.exe
*.exe~ *.exe~
*.dll #*.dll
*.so *.so
*.dylib *.dylib
@@ -5,11 +5,16 @@ using System.Text;
namespace Interact namespace Interact
{ {
//字符串常量 //Json数据的字段访问字符串
public static class Strings public static class AttrNames
{ {
public const string Token = "Token"; public const string Token = "Token";
public const string Operation = "Operation"; public const string Operation = "Operation";
public const string Error = "Error"; 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.Net;
using System.Threading; using System.Threading;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using Newtonsoft.Json.Linq; using System.Drawing;
namespace Interact namespace Interact
{ {
//连接中断 //连接中断
public delegate void DisconnectHandler(Exception ex); 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 partial class StormClient
{ {
//连接中断事件 //连接中断事件
public static event DisconnectHandler OnDisconnect; 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 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客户端 //TCP客户端
private static TcpClient tcpClient; private static TcpClient tcpClient;
@@ -30,12 +68,15 @@ namespace Interact
private static Thread readLoopThread; private static Thread readLoopThread;
//数据发送线程 //数据发送线程
private static Thread sendLoopThread; private static Thread sendLoopThread;
//发送消息时是否要求服务器返回处理结果
private static volatile int doesSendMessageReturn = 0;
static StormClient() static StormClient()
{ {
tcpClient = new TcpClient(); tcpClient = new TcpClient();
sendQueue = new BlockingCollection<Packet>(); sendQueue = new BlockingCollection<Packet>();
} }
/// <summary> /// <summary>
/// 初始化客户端,连接服务器。如果成功则启动数据接收和发送线程 /// 初始化客户端,连接服务器。如果成功则启动数据接收和发送线程
/// </summary> /// </summary>
@@ -62,7 +103,7 @@ namespace Interact
} }
/// <summary> /// <summary>
/// 登录。此操作为异步操作,完成后产生OnLoginDone事件。 /// 登录。此操作为异步操作,服务器返回结果后产生OnLoginDone事件。
/// </summary> /// </summary>
/// <returns>成功将请求加入发送队列返回true,否则返回false。</returns> /// <returns>成功将请求加入发送队列返回true,否则返回false。</returns>
/// <param name="user">用户名</param> /// <param name="user">用户名</param>
+30 -7
View File
@@ -14,10 +14,10 @@ namespace Interact
{ {
string head = Encoding.UTF8.GetString(headData); string head = Encoding.UTF8.GetString(headData);
JObject jsonObj = (JObject)JsonConvert.DeserializeObject(head); 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: case Operations.Login:
HandleLoginResult(jsonObj, data); HandleLoginResult(GetResultHead(jsonObj), data);
break; break;
case Operations.Panic: case Operations.Panic:
case Operations.TransMessage: case Operations.TransMessage:
@@ -32,14 +32,37 @@ namespace Interact
break; break;
} }
} }
//处理登录反馈消息
private static void HandleLoginResult(JObject head, byte[] data) //提取基本结果包头结构
private static ResultHead GetResultHead(JObject head)
{ {
User user = null; ResultHead resultHead = new ResultHead
if (head[Strings.Error].ToString() == "") {
user = JsonConvert.DeserializeObject<User>(Encoding.UTF8.GetString(data)) as User; 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); OnLoginDone?.Invoke(head, user);
} }
} }
} }
+2 -1
View File
@@ -36,6 +36,7 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@@ -55,7 +56,7 @@
</Compile> </Compile>
<Compile Include="Read.cs" /> <Compile Include="Read.cs" />
<Compile Include="Send.cs" /> <Compile Include="Send.cs" />
<Compile Include="Strings.cs" /> <Compile Include="AttrNames.cs" />
<Compile Include="User.cs" /> <Compile Include="User.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+27 -2
View File
@@ -3,10 +3,26 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
//此文件定义Json序列化与反序列化时使用的数据结构,仅内部使用
namespace Interact 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 internal class JsonLogInfoHead : BaseHead
{ {
@@ -14,4 +30,13 @@ namespace Interact
public string Pwd; 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 namespace Interact
{ {
//定义一则用户消息 //定义一则用户接收到的消息
public class Message 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 DateTime When { get; } //服务器接收时间
public User From; //发送者 public User From; //发送者
public string Content; //消息内容 public string Content; //消息内容
}
//将消息保存到数据库(保留)
//包头基本结构 protected bool Save() { return false; }
public class BaseHead
{
//请求ID,由发送方定义的随机字符串。如果接受方有返回数据应包含相同的Token
public string Token;
//操作类型,决定数据的其他内容
public string Operation;
}
// 接受方返回的执行结果反馈包头,包含错误文本
public class ResultHead : BaseHead
{
//错误文本,为空则执行成功
public string Error;
} }
//从服务器接收的原始数据封包 //从服务器接收的原始数据封包
Binary file not shown.
+4 -3
View File
@@ -36,16 +36,17 @@ namespace StormChat
} }
//登录结果处理 //登录结果处理
private void LoginDone(JObject head, User user) private void LoginDone(ResultHead head, User user)
{ {
Action f = delegate () Action f = delegate ()
{ {
btnLogin.Enabled = true; btnLogin.Enabled = true;
if (head[Strings.Error].ToString() != "") if (head.Error != "")
{ {
MessageBox.Show("登录失败:" + head[Strings.Error].ToString()); MessageBox.Show("登录失败:" + head.Error);
return; return;
} }
User.Me = user;
_mainForm.Opacity = 1; _mainForm.Opacity = 1;
_mainForm.Show(); _mainForm.Show();
this.Close(); this.Close();
+1 -2
View File
@@ -44,8 +44,7 @@
<ApplicationManifest>Properties\app.manifest</ApplicationManifest> <ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Interact\Newtonsoft.Json.dll</HintPath> <HintPath>..\Interact\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />