feat:增加单聊消息模块
This commit is contained in:
@@ -13,13 +13,13 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace SweetChatService.Handlers
|
namespace SweetChatService.Handlers
|
||||||
{
|
{
|
||||||
internal class WebSocketMessageHandler(ILogger<WebSocketMessageHandler> logger,
|
internal class WsMsgHandler(ILogger<WsMsgHandler> logger,
|
||||||
WebSocketSessionManager sessionManager,
|
WsSessionManager sessionManager,
|
||||||
UserService userService)
|
PrivateChatService privateChatService)
|
||||||
{
|
{
|
||||||
private readonly ILogger<WebSocketMessageHandler> _logger = logger;
|
private readonly ILogger<WsMsgHandler> _logger = logger;
|
||||||
private readonly WebSocketSessionManager _sessionManager = sessionManager;
|
private readonly WsSessionManager _sessionManager = sessionManager;
|
||||||
private readonly UserService _userService = userService;
|
private readonly PrivateChatService _privateChatService = privateChatService;
|
||||||
|
|
||||||
public async ValueTask HandleAsync(WebSocketSession session, WebSocketPackage package)
|
public async ValueTask HandleAsync(WebSocketSession session, WebSocketPackage package)
|
||||||
{
|
{
|
||||||
@@ -55,20 +55,17 @@ namespace SweetChatService.Handlers
|
|||||||
{
|
{
|
||||||
switch (msg.Type)
|
switch (msg.Type)
|
||||||
{
|
{
|
||||||
case ImMessageType.CHAT:
|
case ImMessageType.CHAT_PRIVATE:
|
||||||
if (_sessionManager.TryGet(msg.To, out var toSession))
|
await _privateChatService.HandleAsync(msg);
|
||||||
{
|
|
||||||
await toSession.SendAsync(msg.Content);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ImMessageType.ONLINE:
|
case ImMessageType.ONLINE:
|
||||||
_sessionManager.Add(msg.From, session);
|
_sessionManager.Add(msg.From, session);
|
||||||
await session.SendAsync("ok");
|
await session.SendAsync(ImMessage.SystemMessage(msg.From, "OK").ToJson());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ImMessageType.HEARTBEAT:
|
case ImMessageType.HEARTBEAT:
|
||||||
await session.SendAsync("ok");
|
await session.SendAsync(ImMessage.SystemMessage(msg.From, "OK").ToJson());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ using System.Collections.Concurrent;
|
|||||||
|
|
||||||
namespace SweetChatService.Handlers
|
namespace SweetChatService.Handlers
|
||||||
{
|
{
|
||||||
internal class WebSocketSessionManager
|
internal class WsSessionManager
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, WebSocketSession> _sessions = new();
|
private readonly ConcurrentDictionary<string, WebSocketSession> _sessions = new();
|
||||||
|
|
||||||
@@ -17,6 +17,19 @@ namespace SweetChatService.Handlers
|
|||||||
_sessions.TryRemove(userId, out _);
|
_sessions.TryRemove(userId, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RemoveBySession(string sessionId)
|
||||||
|
{
|
||||||
|
var keys = _sessions
|
||||||
|
.Where(x => ReferenceEquals(x.Value.SessionID, sessionId))
|
||||||
|
.Select(x => x.Key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var key in keys)
|
||||||
|
{
|
||||||
|
_sessions.TryRemove(key, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGet(string userId, out WebSocketSession? session)
|
public bool TryGet(string userId, out WebSocketSession? session)
|
||||||
{
|
{
|
||||||
return _sessions.TryGetValue(userId, out session);
|
return _sessions.TryGetValue(userId, out session);
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace SweetChatService.Models
|
namespace SweetChatService.Models
|
||||||
{
|
{
|
||||||
@@ -15,5 +16,28 @@ namespace SweetChatService.Models
|
|||||||
|
|
||||||
[JsonPropertyName("content")]
|
[JsonPropertyName("content")]
|
||||||
public string Content { get; set; } = default!;
|
public string Content { get; set; } = default!;
|
||||||
|
|
||||||
|
public static ImMessage SystemMessage(string to, string content)
|
||||||
|
{
|
||||||
|
return new ImMessage
|
||||||
|
{
|
||||||
|
Type = ImMessageType.SYSTEM,
|
||||||
|
From = "SYSTEM",
|
||||||
|
To = to,
|
||||||
|
Content = content
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 转为 JSON 字符串
|
||||||
|
/// </summary>
|
||||||
|
public string ToJson()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Serialize(this, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ namespace SweetChatService.Models
|
|||||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
internal enum ImMessageType
|
internal enum ImMessageType
|
||||||
{
|
{
|
||||||
CHAT,
|
CHAT_PRIVATE,
|
||||||
|
CHAT_GROUP,
|
||||||
ONLINE,
|
ONLINE,
|
||||||
HEARTBEAT,
|
HEARTBEAT,
|
||||||
SYSTEM,
|
SYSTEM,
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ var host = Host.CreateDefaultBuilder(args)
|
|||||||
})
|
})
|
||||||
.ConfigureServices((context, services) =>
|
.ConfigureServices((context, services) =>
|
||||||
{
|
{
|
||||||
services.AddSingleton<WebSocketMessageHandler>();
|
services.AddSingleton<WsMsgHandler>();
|
||||||
services.AddSingleton<WebSocketSessionManager>();
|
services.AddSingleton<WsSessionManager>();
|
||||||
|
|
||||||
|
services.AddSingleton<PrivateChatService>();
|
||||||
|
|
||||||
services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"]));
|
services.AddSingleton(FreeSqlSetup.CreateFreeSql(context.Configuration["ConnectionStrings:Default"]));
|
||||||
services.AddSingleton<UserService>();
|
services.AddSingleton<UserService>();
|
||||||
@@ -22,18 +24,20 @@ var host = Host.CreateDefaultBuilder(args)
|
|||||||
.AddWebSocketServer(builder =>
|
.AddWebSocketServer(builder =>
|
||||||
{
|
{
|
||||||
builder
|
builder
|
||||||
//.UseSessionHandler(async (session) =>
|
.UseSessionHandler(async (session) =>
|
||||||
//{
|
{
|
||||||
// Console.WriteLine($"Client connected: {session.SessionID}");
|
|
||||||
//},
|
},
|
||||||
//async (session, error) =>
|
async (session, error) =>
|
||||||
//{
|
{
|
||||||
// Console.WriteLine($"Client disconnected: {session.SessionID}");
|
using var scope = session.Server.ServiceProvider.CreateScope();
|
||||||
//})
|
var manager = scope.ServiceProvider.GetRequiredService<WsSessionManager>();
|
||||||
|
manager.RemoveBySession(session.SessionID);
|
||||||
|
})
|
||||||
.UseWebSocketMessageHandler(async (session, package) =>
|
.UseWebSocketMessageHandler(async (session, package) =>
|
||||||
{
|
{
|
||||||
using var scope = session.Server.ServiceProvider.CreateScope();
|
using var scope = session.Server.ServiceProvider.CreateScope();
|
||||||
var handler = scope.ServiceProvider.GetRequiredService<WebSocketMessageHandler>();
|
var handler = scope.ServiceProvider.GetRequiredService<WsMsgHandler>();
|
||||||
|
|
||||||
await handler.HandleAsync(session, package);
|
await handler.HandleAsync(session, package);
|
||||||
})
|
})
|
||||||
|
|||||||
26
SweetChatService/Services/PrivateChatService.cs
Normal file
26
SweetChatService/Services/PrivateChatService.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using SweetChatService.Handlers;
|
||||||
|
using SweetChatService.Models;
|
||||||
|
|
||||||
|
namespace SweetChatService.Services
|
||||||
|
{
|
||||||
|
internal class PrivateChatService(WsSessionManager wsSessionManager)
|
||||||
|
{
|
||||||
|
private readonly WsSessionManager _wsSessionManager = wsSessionManager;
|
||||||
|
|
||||||
|
public async Task HandleAsync(ImMessage msg)
|
||||||
|
{
|
||||||
|
// 推送给对方
|
||||||
|
if (_wsSessionManager.TryGet(msg.To, out var toSession))
|
||||||
|
{
|
||||||
|
await toSession.SendAsync(msg.ToJson());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 推送给自己
|
||||||
|
if (_wsSessionManager.TryGet(msg.From, out var fromSession))
|
||||||
|
{
|
||||||
|
await fromSession.SendAsync(msg.ToJson());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=123456;Charset=utf8mb4;"
|
"Default": "Server=localhost;Port=3306;Database=sweet_chat;Uid=root;Pwd=estun@medical;Charset=utf8mb4;"
|
||||||
},
|
},
|
||||||
"serverOptions": {
|
"serverOptions": {
|
||||||
"WebSocketServer": {
|
"WebSocketServer": {
|
||||||
|
|||||||
Reference in New Issue
Block a user