* LCIMClient.cs:
* LCConnection.cs: * LCWebSocketClient.cs: * Program.cs: chore
parent
aeb063f6f8
commit
b89709b21d
|
@ -9,6 +9,9 @@ using LeanCloud.Common;
|
||||||
using LeanCloud.Storage;
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime.Internal.Connection {
|
namespace LeanCloud.Realtime.Internal.Connection {
|
||||||
|
/// <summary>
|
||||||
|
/// 连接层,只与数据协议相关
|
||||||
|
/// </summary>
|
||||||
internal class LCConnection {
|
internal class LCConnection {
|
||||||
private const int SEND_TIMEOUT = 10000;
|
private const int SEND_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ using LeanCloud.Common;
|
||||||
using LeanCloud.Realtime.Internal.Router;
|
using LeanCloud.Realtime.Internal.Router;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime.Internal.WebSocket {
|
namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket 客户端,只与通信协议相关
|
||||||
|
/// </summary>
|
||||||
internal class LCWebSocketClient {
|
internal class LCWebSocketClient {
|
||||||
// .net standard 2.0 好像在拼合 Frame 时有 bug,所以将这个值调整大一些
|
// .net standard 2.0 好像在拼合 Frame 时有 bug,所以将这个值调整大一些
|
||||||
private const int RECV_BUFFER_SIZE = 1024 * 5;
|
private const int RECV_BUFFER_SIZE = 1024 * 5;
|
||||||
|
@ -28,11 +31,11 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
internal async Task Connect() {
|
internal async Task Connect() {
|
||||||
LCRTMServer rtmServer = await router.GetServer();
|
LCRTMServer rtmServer = await router.GetServer();
|
||||||
try {
|
try {
|
||||||
LCLogger.Debug($"Connect Primary Server");
|
LCLogger.Debug($"Primary Server");
|
||||||
await Connect(rtmServer.Primary);
|
await Connect(rtmServer.Primary);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LCLogger.Error(e.Message);
|
LCLogger.Error(e.Message);
|
||||||
LCLogger.Debug($"Connect Secondary");
|
LCLogger.Debug($"Secondary Server");
|
||||||
await Connect(rtmServer.Secondary);
|
await Connect(rtmServer.Secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +44,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Connect(string server) {
|
private async Task Connect(string server) {
|
||||||
LCLogger.Debug($"Connect WebSocket: {server}");
|
LCLogger.Debug($"Connecting WebSocket: {server}");
|
||||||
Task timeoutTask = Task.Delay(5000);
|
Task timeoutTask = Task.Delay(5000);
|
||||||
ws = new ClientWebSocket();
|
ws = new ClientWebSocket();
|
||||||
ws.Options.AddSubProtocol("lc.protobuf2.3");
|
ws.Options.AddSubProtocol("lc.protobuf2.3");
|
||||||
|
@ -54,6 +57,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task Close() {
|
internal async Task Close() {
|
||||||
|
LCLogger.Debug("Closing WebSocket");
|
||||||
OnMessage = null;
|
OnMessage = null;
|
||||||
OnDisconnect = null;
|
OnDisconnect = null;
|
||||||
OnReconnect = null;
|
OnReconnect = null;
|
||||||
|
@ -68,7 +72,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
} finally {
|
} finally {
|
||||||
ws.Abort();
|
ws.Abort();
|
||||||
ws.Dispose();
|
ws.Dispose();
|
||||||
LCLogger.Debug("Closed WebSocket.");
|
LCLogger.Debug("Closed WebSocket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +86,9 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Exception($"Error Websocket state: {ws.State}");
|
string message = $"Error Websocket state: {ws.State}";
|
||||||
|
LCLogger.Error(message);
|
||||||
|
throw new Exception(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ using LeanCloud.Realtime.Internal.Controller;
|
||||||
using LeanCloud.Realtime.Internal.Connection;
|
using LeanCloud.Realtime.Internal.Connection;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
|
/// <summary>
|
||||||
|
/// 通信客户端
|
||||||
|
/// </summary>
|
||||||
public class LCIMClient {
|
public class LCIMClient {
|
||||||
internal Dictionary<string, LCIMConversation> ConversationDict;
|
internal Dictionary<string, LCIMConversation> ConversationDict;
|
||||||
|
|
||||||
|
@ -185,6 +188,20 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息已送达
|
||||||
|
/// </summary>
|
||||||
|
public Action<LCIMConversation, string> OnMessageDelivered {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息已读
|
||||||
|
/// </summary>
|
||||||
|
public Action<LCIMConversation, string> OnMessageRead {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 未读消息数目更新
|
/// 未读消息数目更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -233,6 +250,10 @@ namespace LeanCloud.Realtime {
|
||||||
get; private set;
|
get; private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LCIMRcpController RcpController {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
#region 接口
|
#region 接口
|
||||||
|
|
||||||
public LCIMClient(string clientId,
|
public LCIMClient(string clientId,
|
||||||
|
@ -246,6 +267,7 @@ namespace LeanCloud.Realtime {
|
||||||
MessageController = new LCIMMessageController(this);
|
MessageController = new LCIMMessageController(this);
|
||||||
UnreadController = new LCIMUnreadController(this);
|
UnreadController = new LCIMUnreadController(this);
|
||||||
GoAwayController = new LCIMGoAwayController(this);
|
GoAwayController = new LCIMGoAwayController(this);
|
||||||
|
RcpController = new LCIMRcpController(this);
|
||||||
|
|
||||||
Connection = new LCConnection(Id) {
|
Connection = new LCConnection(Id) {
|
||||||
OnNotification = OnConnectionNotification,
|
OnNotification = OnConnectionNotification,
|
||||||
|
@ -410,6 +432,9 @@ namespace LeanCloud.Realtime {
|
||||||
case CommandType.Goaway:
|
case CommandType.Goaway:
|
||||||
_ = GoAwayController.OnNotification(notification);
|
_ = GoAwayController.OnNotification(notification);
|
||||||
break;
|
break;
|
||||||
|
case CommandType.Rcp:
|
||||||
|
_ = RcpController.OnNotification(notification);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,23 @@ namespace RealtimeConsole {
|
||||||
|
|
||||||
LCLogger.LogDelegate += (level, info) => {
|
LCLogger.LogDelegate += (level, info) => {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LCLogLevel.Debug:
|
case LCLogLevel.Debug: {
|
||||||
Console.WriteLine($"[DEBUG]\n{info}");
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Console.WriteLine($"{DateTime.Now} [DEBUG]\n{info}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LCLogLevel.Warn:
|
case LCLogLevel.Warn: {
|
||||||
Console.WriteLine($"[WARNING]\n{info}");
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine($"{DateTime.Now} [WARNING]\n{info}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LCLogLevel.Error:
|
case LCLogLevel.Error: {
|
||||||
Console.WriteLine($"[ERROR]\n{info}");
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine($"{DateTime.Now} [ERROR]\n{info}");
|
||||||
|
Console.ResetColor();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Console.WriteLine(info);
|
Console.WriteLine(info);
|
||||||
|
@ -32,14 +41,22 @@ namespace RealtimeConsole {
|
||||||
|
|
||||||
SingleThreadSynchronizationContext.Run(async () => {
|
SingleThreadSynchronizationContext.Run(async () => {
|
||||||
Console.WriteLine($"start at {Thread.CurrentThread.ManagedThreadId}");
|
Console.WriteLine($"start at {Thread.CurrentThread.ManagedThreadId}");
|
||||||
await Run("cc4");
|
//await Run("cc1");
|
||||||
//await ChatRoom();
|
//await ChatRoom();
|
||||||
//await TemporaryConversation();
|
//await TemporaryConversation();
|
||||||
//await CreateConversation();
|
//await CreateConversation();
|
||||||
//await QueryMyConversation();
|
//await QueryMyConversation();
|
||||||
|
//await AutoSendMessage();
|
||||||
|
|
||||||
|
//await KeepAlive();
|
||||||
|
|
||||||
|
await OpenAndClose();
|
||||||
|
|
||||||
Console.WriteLine($"done at {Thread.CurrentThread.ManagedThreadId}");
|
Console.WriteLine($"done at {Thread.CurrentThread.ManagedThreadId}");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//AutoSendMessage().Wait();
|
||||||
|
|
||||||
//Conversation().Wait();
|
//Conversation().Wait();
|
||||||
|
|
||||||
//_ = Signature();
|
//_ = Signature();
|
||||||
|
@ -65,6 +82,24 @@ namespace RealtimeConsole {
|
||||||
Console.ReadKey(true);
|
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() {
|
static async Task DemoAsync() {
|
||||||
Dictionary<int, int> d = new Dictionary<int, int>();
|
Dictionary<int, int> d = new Dictionary<int, int>();
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
@ -86,17 +121,16 @@ namespace RealtimeConsole {
|
||||||
Console.WriteLine($"unread: {conv.Id}");
|
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}");
|
Console.WriteLine($"recv: {conversation.Id}, {message.Id} at {Thread.CurrentThread.ManagedThreadId}");
|
||||||
|
await conversation.Read();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task CreateConversation() {
|
static async Task CreateConversation() {
|
||||||
LCIMClient cc1 = new LCIMClient("cc1");
|
LCIMClient cc1 = new LCIMClient("cc1");
|
||||||
await cc1.Open();
|
await cc1.Open();
|
||||||
//await cc1.CreateChatRoom("leancloud chat");
|
await cc1.CreateConversation(new string[] { "cc2", "cc3", "cc5" });
|
||||||
await cc1.CreateTemporaryConversation(new string[] { "cc2", "cc3" });
|
|
||||||
//await cc1.CreateConversation(new string[] { "cc4" });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task QueryMyConversation() {
|
static async Task QueryMyConversation() {
|
||||||
|
@ -146,6 +180,7 @@ namespace RealtimeConsole {
|
||||||
static async Task OpenAndClose() {
|
static async Task OpenAndClose() {
|
||||||
LCIMClient o1 = new LCIMClient("o1");
|
LCIMClient o1 = new LCIMClient("o1");
|
||||||
await o1.Open();
|
await o1.Open();
|
||||||
|
await Task.Delay(30000);
|
||||||
await o1.Close();
|
await o1.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue