* LCIMClient.cs:

* LCConnection.cs:
* LCWebSocketClient.cs:

* Program.cs: chore
oneRain 2020-04-13 10:47:14 +08:00
parent aeb063f6f8
commit b89709b21d
4 changed files with 85 additions and 16 deletions

View File

@ -9,6 +9,9 @@ using LeanCloud.Common;
using LeanCloud.Storage;
namespace LeanCloud.Realtime.Internal.Connection {
/// <summary>
/// 连接层,只与数据协议相关
/// </summary>
internal class LCConnection {
private const int SEND_TIMEOUT = 10000;

View File

@ -5,6 +5,9 @@ using LeanCloud.Common;
using LeanCloud.Realtime.Internal.Router;
namespace LeanCloud.Realtime.Internal.WebSocket {
/// <summary>
/// WebSocket 客户端,只与通信协议相关
/// </summary>
internal class LCWebSocketClient {
// .net standard 2.0 好像在拼合 Frame 时有 bug所以将这个值调整大一些
private const int RECV_BUFFER_SIZE = 1024 * 5;
@ -28,11 +31,11 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
internal async Task Connect() {
LCRTMServer rtmServer = await router.GetServer();
try {
LCLogger.Debug($"Connect Primary Server");
LCLogger.Debug($"Primary Server");
await Connect(rtmServer.Primary);
} catch (Exception e) {
LCLogger.Error(e.Message);
LCLogger.Debug($"Connect Secondary");
LCLogger.Debug($"Secondary Server");
await Connect(rtmServer.Secondary);
}
@ -41,7 +44,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
}
private async Task Connect(string server) {
LCLogger.Debug($"Connect WebSocket: {server}");
LCLogger.Debug($"Connecting WebSocket: {server}");
Task timeoutTask = Task.Delay(5000);
ws = new ClientWebSocket();
ws.Options.AddSubProtocol("lc.protobuf2.3");
@ -54,6 +57,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
}
internal async Task Close() {
LCLogger.Debug("Closing WebSocket");
OnMessage = null;
OnDisconnect = null;
OnReconnect = null;
@ -68,7 +72,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
} finally {
ws.Abort();
ws.Dispose();
LCLogger.Debug("Closed WebSocket.");
LCLogger.Debug("Closed WebSocket");
}
}
@ -82,7 +86,9 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
throw e;
}
} else {
throw new Exception($"Error Websocket state: {ws.State}");
string message = $"Error Websocket state: {ws.State}";
LCLogger.Error(message);
throw new Exception(message);
}
}

View File

@ -9,6 +9,9 @@ using LeanCloud.Realtime.Internal.Controller;
using LeanCloud.Realtime.Internal.Connection;
namespace LeanCloud.Realtime {
/// <summary>
/// 通信客户端
/// </summary>
public class LCIMClient {
internal Dictionary<string, LCIMConversation> ConversationDict;
@ -185,6 +188,20 @@ namespace LeanCloud.Realtime {
get; set;
}
/// <summary>
/// 消息已送达
/// </summary>
public Action<LCIMConversation, string> OnMessageDelivered {
get; set;
}
/// <summary>
/// 消息已读
/// </summary>
public Action<LCIMConversation, string> OnMessageRead {
get; set;
}
/// <summary>
/// 未读消息数目更新
/// </summary>
@ -233,6 +250,10 @@ namespace LeanCloud.Realtime {
get; private set;
}
internal LCIMRcpController RcpController {
get; private set;
}
#region 接口
public LCIMClient(string clientId,
@ -246,6 +267,7 @@ namespace LeanCloud.Realtime {
MessageController = new LCIMMessageController(this);
UnreadController = new LCIMUnreadController(this);
GoAwayController = new LCIMGoAwayController(this);
RcpController = new LCIMRcpController(this);
Connection = new LCConnection(Id) {
OnNotification = OnConnectionNotification,
@ -410,6 +432,9 @@ namespace LeanCloud.Realtime {
case CommandType.Goaway:
_ = GoAwayController.OnNotification(notification);
break;
case CommandType.Rcp:
_ = RcpController.OnNotification(notification);
break;
default:
break;
}

View File

@ -14,14 +14,23 @@ namespace RealtimeConsole {
LCLogger.LogDelegate += (level, info) => {
switch (level) {
case LCLogLevel.Debug:
Console.WriteLine($"[DEBUG]\n{info}");
case LCLogLevel.Debug: {
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"{DateTime.Now} [DEBUG]\n{info}");
Console.ResetColor();
}
break;
case LCLogLevel.Warn:
Console.WriteLine($"[WARNING]\n{info}");
case LCLogLevel.Warn: {
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"{DateTime.Now} [WARNING]\n{info}");
Console.ResetColor();
}
break;
case LCLogLevel.Error:
Console.WriteLine($"[ERROR]\n{info}");
case LCLogLevel.Error: {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"{DateTime.Now} [ERROR]\n{info}");
Console.ResetColor();
}
break;
default:
Console.WriteLine(info);
@ -32,14 +41,22 @@ namespace RealtimeConsole {
SingleThreadSynchronizationContext.Run(async () => {
Console.WriteLine($"start at {Thread.CurrentThread.ManagedThreadId}");
await Run("cc4");
//await Run("cc1");
//await ChatRoom();
//await TemporaryConversation();
//await CreateConversation();
//await QueryMyConversation();
//await AutoSendMessage();
//await KeepAlive();
await OpenAndClose();
Console.WriteLine($"done at {Thread.CurrentThread.ManagedThreadId}");
});
//AutoSendMessage().Wait();
//Conversation().Wait();
//_ = Signature();
@ -65,6 +82,24 @@ namespace RealtimeConsole {
Console.ReadKey(true);
}
static async Task KeepAlive() {
LCIMClient client = new LCIMClient("cc1");
await client.Open();
}
static async Task AutoSendMessage() {
LCIMClient client = new LCIMClient("cc1");
await client.Open();
LCIMConversation conversation = await client.CreateConversation(new string[] { "cc2", "cc3", "cc5" });
int count = 0;
while (count < 10) {
LCIMTextMessage textMessage = new LCIMTextMessage($"hello, {count}");
await conversation.Send(textMessage);
await Task.Delay(5000);
count++;
}
}
static async Task DemoAsync() {
Dictionary<int, int> d = new Dictionary<int, int>();
for (int i = 0; i < 10000; i++) {
@ -86,17 +121,16 @@ namespace RealtimeConsole {
Console.WriteLine($"unread: {conv.Id}");
}
};
client.OnMessage = (conversation, message) => {
client.OnMessage = async (conversation, message) => {
Console.WriteLine($"recv: {conversation.Id}, {message.Id} at {Thread.CurrentThread.ManagedThreadId}");
await conversation.Read();
};
}
static async Task CreateConversation() {
LCIMClient cc1 = new LCIMClient("cc1");
await cc1.Open();
//await cc1.CreateChatRoom("leancloud chat");
await cc1.CreateTemporaryConversation(new string[] { "cc2", "cc3" });
//await cc1.CreateConversation(new string[] { "cc4" });
await cc1.CreateConversation(new string[] { "cc2", "cc3", "cc5" });
}
static async Task QueryMyConversation() {
@ -146,6 +180,7 @@ namespace RealtimeConsole {
static async Task OpenAndClose() {
LCIMClient o1 = new LCIMClient("o1");
await o1.Open();
await Task.Delay(30000);
await o1.Close();
}