修改获取用户列表API

This commit is contained in:
Mattuy
2018-12-17 21:53:52 +08:00
parent 9894de2953
commit 82bc190cf9
10 changed files with 145 additions and 96 deletions
+40 -65
View File
@@ -1,18 +1,14 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Net.Sockets; using System.Net.Sockets;
using System.Net;
using System.Threading; using System.Threading;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Drawing;
using System.IO; using System.IO;
namespace Interact namespace Interact
{ {
//连接中断 //连接中断
public delegate void DisconnectHandler(Exception ex); public delegate void ConnectionBrokenHandler(Exception ex);
//通用请求结果处理 //通用请求结果处理
public delegate void ResultHandler(ResultHead head); public delegate void ResultHandler(ResultHead head);
//消息到达事件处理 //消息到达事件处理
@@ -21,9 +17,6 @@ namespace Interact
public delegate void LoginDoneHandler(ResultHead head, User user); public delegate void LoginDoneHandler(ResultHead head, User user);
//获取用户列表结果处理 //获取用户列表结果处理
public delegate void GetUserListDoneHandler(ResultHead head, User[] users); public delegate void GetUserListDoneHandler(ResultHead head, User[] users);
//获取用户头像结果处理
public delegate void GetUserPhotoDoneHandler(ResultHead head, Image image);
/// <summary> /// <summary>
/// 与服务器进行数据通信,并向外部提供一系列通信接口 /// 与服务器进行数据通信,并向外部提供一系列通信接口
@@ -31,7 +24,7 @@ namespace Interact
public static partial class StormClient public static partial class StormClient
{ {
//连接中断事件 //连接中断事件
public static event DisconnectHandler OnDisconnect; public static event ConnectionBrokenHandler OnDisconnect;
//服务器异常消息处理事件 //服务器异常消息处理事件
public static event ResultHandler OnPanic; public static event ResultHandler OnPanic;
//服务器强制注销登陆事件 //服务器强制注销登陆事件
@@ -45,37 +38,27 @@ namespace Interact
//登录结果处理事件 //登录结果处理事件
public static event LoginDoneHandler OnLoginDone; public static event LoginDoneHandler OnLoginDone;
//获取用户列表结果处理事件 //获取用户列表结果处理事件
public static event GetUserListDoneHandler OnGetUserListDone; private static event GetUserListDoneHandler OnGetUserListDone;
//获取用户头像结果处理事件
public static event GetUserPhotoDoneHandler OnGetUserPhotoDone; //当前连接状态
public static ClientStatus Status
{
get { lock (statusLocker) { return clientStatus; } }
set { lock (statusLocker) { clientStatus = value; } }
}
//发送消息时是否要求服务器返回处理结果 //发送消息时是否要求服务器返回处理结果
public static bool DoesSendMessageReturn public static bool DoesSendMessageReturn
{ {
get get { lock (doesSendMessageReturnLocker) { return doesSendMessageReturnResult; } }
{ set { lock (doesSendMessageReturnLocker) { doesSendMessageReturnResult = value; } }
return doesSendMessageReturn != 0;
}
set
{
Interlocked.Exchange(ref StormClient.doesSendMessageReturn, value ? 1 : 0);
}
} }
//TCP客户端
private static TcpClient tcpClient;
//消息发送队列
private static BlockingCollection<Packet> sendQueue;
//数据读取线程
private static Thread readLoopThread;
//数据发送线程
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>();
Status = ClientStatus.Uninitialized;
} }
/// <summary> /// <summary>
@@ -87,7 +70,14 @@ namespace Interact
{ {
if (StormClient.tcpClient.Connected) if (StormClient.tcpClient.Connected)
return true; return true;
StormClient.tcpClient.Connect(Interact.Properties.Resources.RemoteServerAddr, int.Parse(Interact.Properties.Resources.RemoteServerPort)); try
{
StormClient.tcpClient.Connect(Interact.Properties.Resources.RemoteServerAddr, int.Parse(Interact.Properties.Resources.RemoteServerPort));
}
catch (Exception)
{
return false;
}
if (!StormClient.tcpClient.Connected) if (!StormClient.tcpClient.Connected)
return false; return false;
if (sendLoopThread != null) if (sendLoopThread != null)
@@ -97,8 +87,8 @@ namespace Interact
//启动数据收发线程 //启动数据收发线程
sendLoopThread = new Thread(new ThreadStart(SendLoop)); sendLoopThread = new Thread(new ThreadStart(SendLoop));
readLoopThread = new Thread(new ThreadStart(ReadLoop)); readLoopThread = new Thread(new ThreadStart(ReadLoop));
//设置为后台线程
sendLoopThread.IsBackground = readLoopThread.IsBackground = true; sendLoopThread.IsBackground = readLoopThread.IsBackground = true;
StormClient.Status = ClientStatus.Running;
sendLoopThread.Start(); sendLoopThread.Start();
readLoopThread.Start(); readLoopThread.Start();
return true; return true;
@@ -116,7 +106,7 @@ namespace Interact
JsonLogInfoHead logInfo = new JsonLogInfoHead() JsonLogInfoHead logInfo = new JsonLogInfoHead()
{ {
Token = "", Token = "",
Operation = Operations.Login.ToString(), Operation = Operations.Login,
User = user, User = user,
Pwd = password Pwd = password
}; };
@@ -128,7 +118,7 @@ namespace Interact
}; };
return Send(packet); return Send(packet);
} }
/// <summary> /// <summary>
/// 请求发送一条消息。异步,此方法将请求放入请求队列后返回。 /// 请求发送一条消息。异步,此方法将请求放入请求队列后返回。
/// </summary> /// </summary>
@@ -141,7 +131,7 @@ namespace Interact
JsonSendMessageHead jsonObj = new JsonSendMessageHead() JsonSendMessageHead jsonObj = new JsonSendMessageHead()
{ {
Token = "", Token = "",
Operation = Operations.SendMessage.ToString(), Operation = Operations.SendMessage,
To = to.Name, To = to.Name,
NeedResult = DoesSendMessageReturn ? "1" : "0" NeedResult = DoesSendMessageReturn ? "1" : "0"
}; };
@@ -153,7 +143,7 @@ namespace Interact
}; };
return Send(packet); return Send(packet);
} }
/// <summary> /// <summary>
/// 请求登出。异步,此方法将请求放入请求队列后返回。 /// 请求登出。异步,此方法将请求放入请求队列后返回。
/// </summary> /// </summary>
@@ -164,7 +154,7 @@ namespace Interact
BaseHead jsonObj = new BaseHead() BaseHead jsonObj = new BaseHead()
{ {
Token = "", Token = "",
Operation = Operations.Logout.ToString(), Operation = Operations.Logout,
}; };
Packet packet = new Packet Packet packet = new Packet
{ {
@@ -174,7 +164,7 @@ namespace Interact
}; };
return Send(packet); return Send(packet);
} }
/// <summary> /// <summary>
/// 请求用户列表。异步,此方法将请求放入请求队列后返回。 /// 请求用户列表。异步,此方法将请求放入请求队列后返回。
/// </summary> /// </summary>
@@ -185,7 +175,7 @@ namespace Interact
BaseHead jsonObj = new BaseHead() BaseHead jsonObj = new BaseHead()
{ {
Token = "", Token = "",
Operation = Operations.GetUserList.ToString(), Operation = Operations.GetUsers,
}; };
Packet packet = new Packet Packet packet = new Packet
{ {
@@ -195,7 +185,7 @@ namespace Interact
}; };
return Send(packet); return Send(packet);
} }
/// <summary> /// <summary>
/// 请求更新当前登录用户信息。异步,此方法将请求放入请求队列后返回。 /// 请求更新当前登录用户信息。异步,此方法将请求放入请求队列后返回。
/// </summary> /// </summary>
@@ -203,8 +193,8 @@ namespace Interact
/// <returns>成功将请求加入发送队列返回true,否则返回false。</returns> /// <returns>成功将请求加入发送队列返回true,否则返回false。</returns>
public static bool QueueUpdateUserInfo(UserInfo userInfo, Action<BaseHead> callback = null) public static bool QueueUpdateUserInfo(UserInfo userInfo, Action<BaseHead> callback = null)
{ {
byte[] photoData = null; //头像数据 byte[] photoData = null; //头像数据
//将头像数据转换到字符数组 //将头像数据转换到字符数组
if (userInfo.Photo != null) if (userInfo.Photo != null)
{ {
MemoryStream memStream = new MemoryStream(); MemoryStream memStream = new MemoryStream();
@@ -217,7 +207,7 @@ namespace Interact
JsonUserInfoHead jsonObj = new JsonUserInfoHead() JsonUserInfoHead jsonObj = new JsonUserInfoHead()
{ {
Token = "", Token = "",
Operation = Operations.UpdateUserInfo.ToString(), Operation = Operations.UpdateUserInfo,
NickName = userInfo.NickName, NickName = userInfo.NickName,
Password = userInfo.Password, Password = userInfo.Password,
Motto = userInfo.Motto, Motto = userInfo.Motto,
@@ -231,28 +221,13 @@ namespace Interact
}; };
return Send(packet); return Send(packet);
} }
/// <summary> //客户端连接状态
/// 请求获取指定用户的头像。异步,此方法将请求放入请求队列后返回。 public enum ClientStatus
/// </summary>
/// <param name="user">要获取头像的用户</param>
/// <param name="callback">数据发送完毕时回调函数</param>
/// <returns>成功将请求加入发送队列返回true,否则返回false。</returns>
public static bool QueueGetUserPhoto(User user, Action<BaseHead> callback = null)
{ {
JsonGetUserPhotoHead jsonObj = new JsonGetUserPhotoHead() Uninitialized, //未启动
{ Running, //运行中
Token = "", Stopped //已停止
Operation = Operations.GetUserPhoto.ToString(),
User = user.Name
};
Packet packet = new Packet
{
Head = jsonObj,
Data = null,
CallBack = callback
};
return Send(packet);
} }
} }
} }
+12
View File
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Interact
{
class ConnectionBrokenException : Exception
{
public ConnectionBrokenException(string message) : base(message) { }
}
}
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Net.Sockets;
using System.Collections.Concurrent;
using System.Threading;
using System.Collections.Generic;
//定义StormClient私有字段
namespace Interact
{
public partial class StormClient
{
//TCP客户端
private static TcpClient tcpClient;
//消息发送队列
private static BlockingCollection<Packet> sendQueue;
//数据读取线程
private static Thread readLoopThread;
//数据发送线程
private static Thread sendLoopThread;
//某些请求需要持续的等待服务器返回数据包,然后将所有数据包处理后提供给用户
// ,此字段用于暂存这些未接收完全的数据包。它的key是对应请求的Token字串。
private static Dictionary<string, object> workingDictionary;
//属性控制字段,任何地方都不应该修改它们
//发送消息时是否要求服务器返回处理结果。由DoesSendMessageReturn属性控制,不要直接修改这个字段
private static volatile bool doesSendMessageReturnResult = false;
//当前连接状态。由Status属性控制,不要直接修改这个字段
private static volatile ClientStatus clientStatus = ClientStatus.Uninitialized;
//线程安全-锁
//更改连接状态锁
private static object statusLocker = new object();
//"发送消息时是否要求服务器返回处理结果"Falg锁
private static object doesSendMessageReturnLocker = new object();
}
}
+29 -7
View File
@@ -4,35 +4,50 @@ using System.Linq;
using System.Text; using System.Text;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
//StormClient对数据的处理相关内容
namespace Interact namespace Interact
{ {
//对数据的处理相关内容
public partial class StormClient public partial class StormClient
{ {
//处理连接中断异常
private static void HandleConnectionBroken(Exception ex)
{
lock (statusLocker)
{
if (Status != ClientStatus.Running)
return;
statusLocker = ClientStatus.Stopped;
tcpClient.Close();
OnDisconnect?.Invoke(ex);
}
}
#region
//根据包头信息处理数据 //根据包头信息处理数据
private static void HandleAll(byte[] headData, byte[] data) private static void HandleAll(byte[] headData, byte[] data)
{ {
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[AttrNames.Operation].ToString())) switch (jsonObj[AttrNames.Operation].ToString())
{ {
case Operations.Login: case Operations.Login:
HandleLoginResult(GetResultHead(jsonObj), data); HandleLoginResult(GetResultHead(jsonObj), data);
break; break;
case Operations.Panic: case Operations.Panic:
HandlePanic(GetResultHead(jsonObj));
break;
case Operations.TransMessage: case Operations.TransMessage:
case Operations.SendMessage: case Operations.SendMessage:
case Operations.Ping:
case Operations.Logout: case Operations.Logout:
case Operations.Offline: case Operations.Offline:
case Operations.GetUserList:
case Operations.UpdateUserInfo: case Operations.UpdateUserInfo:
case Operations.GetUserPhoto:
default: default:
break; break;
} }
} }
//提取基本结果包头结构 //提取基本结果包头结构
private static ResultHead GetResultHead(JObject head) private static ResultHead GetResultHead(JObject head)
{ {
@@ -45,6 +60,13 @@ namespace Interact
return resultHead; return resultHead;
} }
//处理服务器异常断开连接消息
private static void HandlePanic(ResultHead head)
{
ConnectionBrokenException ex = new ConnectionBrokenException(head.Error);
HandleConnectionBroken(ex);
}
//处理登录反馈消息 //处理登录反馈消息
private static void HandleLoginResult(ResultHead head, byte[] data) private static void HandleLoginResult(ResultHead head, byte[] data)
{ {
@@ -64,7 +86,7 @@ namespace Interact
}; };
OnLoginDone?.Invoke(head, user); OnLoginDone?.Invoke(head, user);
} }
#endregion
} }
+2
View File
@@ -45,6 +45,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Client.cs" /> <Compile Include="Client.cs" />
<Compile Include="Exception.cs" />
<Compile Include="Fields.cs" />
<Compile Include="Handle.cs" /> <Compile Include="Handle.cs" />
<Compile Include="JsonObject.cs" /> <Compile Include="JsonObject.cs" />
<Compile Include="Message.cs" /> <Compile Include="Message.cs" />
+6
View File
@@ -20,6 +20,11 @@ namespace Interact
{ {
//错误文本,为空则执行成功 //错误文本,为空则执行成功
public string Error; public string Error;
}
//获取单一用户信息结果包头
public class GetUserInfoResultHead : ResultHead
{
} }
#endregion #endregion
@@ -52,5 +57,6 @@ namespace Interact
{ {
public string User; //要获取头像的用户名 public string User; //要获取头像的用户名
} }
#endregion #endregion
} }
+9 -11
View File
@@ -30,17 +30,15 @@ namespace Interact
//服务器可能并没有处理完成请求 //服务器可能并没有处理完成请求
} }
//允许请求的操作列表。具体定义见设计文档 //允许请求的操作列表。具体定义见设计文档
public enum Operations public static class Operations
{ {
Panic, public const string Panic = "Panic";
TransMessage, public const string TransMessage = "TransMessage";
SendMessage, public const string SendMessage = "SendMessage";
Ping, public const string Login = "Login2";
Login, public const string Logout = "Logout";
Logout, public const string Offline = "Offline";
Offline, public const string UpdateUserInfo = "UpdateUserInfo";
GetUserList, public const string GetUsers = "GetUsers";
UpdateUserInfo,
GetUserPhoto
} }
} }
+4 -6
View File
@@ -5,9 +5,9 @@ using System.Text;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
//StormClient读取数据相关内容
namespace Interact namespace Interact
{ {
//读取数据相关内容
public partial class StormClient public partial class StormClient
{ {
// 数据读取线程,从tcp连接读取数据 // 数据读取线程,从tcp连接读取数据
@@ -16,7 +16,7 @@ namespace Interact
NetworkStream stream = StormClient.tcpClient.GetStream(); NetworkStream stream = StormClient.tcpClient.GetStream();
try try
{ {
while (tcpClient.Connected) while (StormClient.Status == ClientStatus.Running)
{ {
byte[] head = ReadDataWithLength(stream); byte[] head = ReadDataWithLength(stream);
byte[] data = ReadDataWithLength(stream); byte[] data = ReadDataWithLength(stream);
@@ -25,13 +25,11 @@ namespace Interact
} }
catch (System.IO.IOException ex) catch (System.IO.IOException ex)
{ {
tcpClient.Close(); HandleConnectionBroken(ex);
OnDisconnect(ex);
} }
catch (ObjectDisposedException ex) catch (ObjectDisposedException ex)
{ {
tcpClient.Close(); HandleConnectionBroken(ex);
OnDisconnect(ex);
} }
} }
// 从网络流读取数据 // 从网络流读取数据
+4 -6
View File
@@ -6,9 +6,9 @@ using Newtonsoft.Json;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
//StormClient发送数据相关内容
namespace Interact namespace Interact
{ {
//发送数据相关内容
public partial class StormClient public partial class StormClient
{ {
// 消息写入线程,向tcp连接写入数据 // 消息写入线程,向tcp连接写入数据
@@ -20,7 +20,7 @@ namespace Interact
foreach (Packet packet in sendQueue.GetConsumingEnumerable()) foreach (Packet packet in sendQueue.GetConsumingEnumerable())
{ {
//结束循环 //结束循环
if (!tcpClient.Connected) if (StormClient.Status != ClientStatus.Running)
break; break;
//向tcp连接写数据 //向tcp连接写数据
byte[] lenBuffer; //数据长度缓存 byte[] lenBuffer; //数据长度缓存
@@ -43,13 +43,11 @@ namespace Interact
} }
catch (System.IO.IOException ex) catch (System.IO.IOException ex)
{ {
tcpClient.Close(); HandleConnectionBroken(ex);
OnDisconnect?.Invoke(ex);
} }
catch (ObjectDisposedException ex) catch (ObjectDisposedException ex)
{ {
tcpClient.Close(); HandleConnectionBroken(ex);
OnDisconnect?.Invoke(ex);
} }
} }
//发送数据 //发送数据
+2 -1
View File
@@ -15,7 +15,8 @@ namespace Interact
public string Name; //用户名 public string Name; //用户名
public string NickName; //昵称 public string NickName; //昵称
public string Motto; //个性签名 public string Motto; //个性签名
public UserGroup Group; //用户组 public UserGroup Group; //用户组
public Image Photo; //头像
} }
//更新用户信息时新的用户信息。如果项值为null则不更改相应的信息 //更新用户信息时新的用户信息。如果项值为null则不更改相应的信息