diff --git a/Realtime/Internal/Connection/LCConnection.cs b/Realtime/Internal/Connection/LCConnection.cs index 6b89760..6311b42 100644 --- a/Realtime/Internal/Connection/LCConnection.cs +++ b/Realtime/Internal/Connection/LCConnection.cs @@ -9,6 +9,9 @@ using LeanCloud.Common; using LeanCloud.Storage; namespace LeanCloud.Realtime.Internal.Connection { + /// + /// 连接层,只与数据协议相关 + /// internal class LCConnection { private const int SEND_TIMEOUT = 10000; diff --git a/Realtime/Internal/WebSocket/LCWebSocketClient.cs b/Realtime/Internal/WebSocket/LCWebSocketClient.cs index a055669..c8f2055 100644 --- a/Realtime/Internal/WebSocket/LCWebSocketClient.cs +++ b/Realtime/Internal/WebSocket/LCWebSocketClient.cs @@ -5,6 +5,9 @@ using LeanCloud.Common; using LeanCloud.Realtime.Internal.Router; namespace LeanCloud.Realtime.Internal.WebSocket { + /// + /// WebSocket 客户端,只与通信协议相关 + /// 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); } } diff --git a/Realtime/LCIMClient.cs b/Realtime/LCIMClient.cs index 8e0919b..177b3ca 100644 --- a/Realtime/LCIMClient.cs +++ b/Realtime/LCIMClient.cs @@ -9,6 +9,9 @@ using LeanCloud.Realtime.Internal.Controller; using LeanCloud.Realtime.Internal.Connection; namespace LeanCloud.Realtime { + /// + /// 通信客户端 + /// public class LCIMClient { internal Dictionary ConversationDict; @@ -185,6 +188,20 @@ namespace LeanCloud.Realtime { get; set; } + /// + /// 消息已送达 + /// + public Action OnMessageDelivered { + get; set; + } + + /// + /// 消息已读 + /// + public Action OnMessageRead { + get; set; + } + /// /// 未读消息数目更新 /// @@ -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; } diff --git a/Test/RealtimeConsole/Program.cs b/Test/RealtimeConsole/Program.cs index 4a9ddd0..c884c43 100644 --- a/Test/RealtimeConsole/Program.cs +++ b/Test/RealtimeConsole/Program.cs @@ -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 d = new Dictionary(); 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(); }