diff --git a/chatclient.sln b/chatclient.sln index f12a4a1..bbc5827 100644 --- a/chatclient.sln +++ b/chatclient.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.13.35931.197 d17.13 +VisualStudioVersion = 17.13.35931.197 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chatclient", "chatclient\chatclient.csproj", "{6965B200-D0AA-4729-A5A4-30DFD307EB80}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "chatserver", "chatserver\chatserver.csproj", "{5AE823C9-2275-45F1-B312-0D1ED4237A2D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {6965B200-D0AA-4729-A5A4-30DFD307EB80}.Debug|Any CPU.Build.0 = Debug|Any CPU {6965B200-D0AA-4729-A5A4-30DFD307EB80}.Release|Any CPU.ActiveCfg = Release|Any CPU {6965B200-D0AA-4729-A5A4-30DFD307EB80}.Release|Any CPU.Build.0 = Release|Any CPU + {5AE823C9-2275-45F1-B312-0D1ED4237A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5AE823C9-2275-45F1-B312-0D1ED4237A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AE823C9-2275-45F1-B312-0D1ED4237A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5AE823C9-2275-45F1-B312-0D1ED4237A2D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/chatclient/App.config b/chatclient/App.config index 964a4fb..50b703a 100644 --- a/chatclient/App.config +++ b/chatclient/App.config @@ -3,5 +3,5 @@
- + \ No newline at end of file diff --git a/chatclient/Data/TrayIconManager.cs b/chatclient/Data/TrayIconManager.cs index f1e04dc..29c8c18 100644 --- a/chatclient/Data/TrayIconManager.cs +++ b/chatclient/Data/TrayIconManager.cs @@ -48,7 +48,7 @@ namespace chatclient.Data // 添加菜单项 contextMenu.Items.Add(CreateMenuItem("打开程序", PackIconKind.WindowRestore, OpenApp_Click)); contextMenu.Items.Add(CreateMenuItem("设置", PackIconKind.Cog, Settings_Click)); - contextMenu.Items.Add(new Separator { Style = (Style)Application.Current.Resources["MaterialDesignLightSeparator"] }); + contextMenu.Items.Add(new Separator { Style = (Style)Application.Current.Resources["Separator"] }); //contextMenu.Items.Add(CreateMenuItem("Check for Updates", PackIconKind.Update, Updates_Click)); //contextMenu.Items.Add(CreateMenuItem("Help", PackIconKind.HelpCircle, Help_Click)); //contextMenu.Items.Add(new Separator { Style = (Style)Application.Current.Resources["MaterialDesignLightSeparator"] }); diff --git a/chatclient/Data/chatapi.cs b/chatclient/Data/chatapi.cs index aef143b..15eff90 100644 --- a/chatclient/Data/chatapi.cs +++ b/chatclient/Data/chatapi.cs @@ -4,9 +4,9 @@ namespace chatclient.Data { internal class Server { - public const string ServerUrl = "http://175.24.191.172:5001"; - public const string ServerIP = "175.24.191.172"; - public const int ServerPort = 8889; + public const string ServerUrl = "http://127.0.0.1:5001"; + public const string ServerIP = "127.0.0.1"; + public const int ServerPort = 52006; } internal class LoginData { @@ -21,6 +21,7 @@ namespace chatclient.Data public string? message { get; set; } public string? token { get; set; } public string? username { get; set; } + public string? userid { get; set; } = "Unid"; } internal class SignData { @@ -30,7 +31,7 @@ namespace chatclient.Data } internal class SignResultData { - public bool success { get; set; } = false; + public string? status { get; set; } = null; public string? message { get; set; } = null; } internal class RegisterData @@ -40,14 +41,19 @@ namespace chatclient.Data internal class ChatRegisterData { public string? user { get; set; } = "Unnamed"; + public required string userid { get; set; } = "Unid"; public string? status { get; set; } = null; public string? message { get; set; } = null; - public string? image { get; set; } = null; - public DateTime timestamp { get; set; } = DateTime.Now; + public string? avatar { get; set; } = null; + public MessageType? msgtype { get; set; } = MessageType.Text; + public DateTime? timestamp { get; set; } = DateTime.Now; } internal class ChatData { public required string type { get; set; } = "chat"; public required string message { get; set; } = "message"; + public MessageType? msgtype { get; set; } = MessageType.Text; + public required string userid { get; set; } = "Unid"; + public string? token { get; set; } = null; // 添加token字段 } } diff --git a/chatclient/LoginWindow.xaml b/chatclient/LoginWindow.xaml index 08bb72e..00c9271 100644 --- a/chatclient/LoginWindow.xaml +++ b/chatclient/LoginWindow.xaml @@ -9,7 +9,6 @@ mc:Ignorable="d" Title="LoginWindow" Height="540" Width="330" MinHeight="540" MinWidth="330" MaxHeight="540" MaxWidth="330" ResizeMode="NoResize" Closing="Window_Closing" Loaded="Window_Loaded"> - diff --git a/chatclient/LoginWindow.xaml.cs b/chatclient/LoginWindow.xaml.cs index b27f93a..5b1e999 100644 --- a/chatclient/LoginWindow.xaml.cs +++ b/chatclient/LoginWindow.xaml.cs @@ -108,14 +108,6 @@ namespace chatclient if (Task.IsCompletedSuccessfully) { log.Info("注册请求发送成功"); - Application.Current.Dispatcher.Invoke(() => - { - var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); - if (loginWindow != null) - { - loginWindow.SignMsg = "注册请求已发送,请等待服务器响应"; - } - }); } else { @@ -187,47 +179,47 @@ namespace chatclient } }); } - public static async Task HttpSignRegistryUser(string Username, string Userpassword) - { - try - { - var SignData = new - { - type = "register", - username = Username, - password = Userpassword - }; - string SignJsonData = JsonSerializer.Serialize(SignData); - byte[] dataBytes = Encoding.UTF8.GetBytes(SignJsonData); - var content = new StringContent(SignJsonData, Encoding.UTF8, "application/json"); - var response = await MainWindow.HttpClient.PostAsync($"{Server.ServerUrl}/api/register", content); - var responseBody = await response.Content.ReadAsStringAsync(); - log.Info($"注册请求已发送,响应内容: {responseBody}"); - var signresponse = JsonSerializer.Deserialize(responseBody); - if (signresponse!.success) - { - log.Info($"注册成功: {signresponse.message}"); - await Login(true, Username, Userpassword); - } - else - { - log.Error($"注册失败: {signresponse.message}"); - Application.Current.Dispatcher.Invoke(() => - { - var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); - loginWindow!.SignMsg = signresponse.message; - }); - } - } - catch (Exception ex) - { - log.Error("注册请求发送失败", ex); - } - finally - { - log.Info("注册请求已完成"); - } - } + //public static async Task HttpSignRegistryUser(string Username, string Userpassword) + //{ + // try + // { + // var SignData = new + // { + // type = "register", + // username = Username, + // password = Userpassword + // }; + // string SignJsonData = JsonSerializer.Serialize(SignData); + // byte[] dataBytes = Encoding.UTF8.GetBytes(SignJsonData); + // var content = new StringContent(SignJsonData, Encoding.UTF8, "application/json"); + // var response = await MainWindow.HttpClient.PostAsync($"{Server.ServerUrl}/api/register", content); + // var responseBody = await response.Content.ReadAsStringAsync(); + // log.Info($"注册请求已发送,响应内容: {responseBody}"); + // var signresponse = JsonSerializer.Deserialize(responseBody); + // if (signresponse!.status) + // { + // log.Info($"注册成功: {signresponse.message}"); + // await Login(true, Username, Userpassword); + // } + // else + // { + // log.Error($"注册失败: {signresponse.message}"); + // Application.Current.Dispatcher.Invoke(() => + // { + // var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + // loginWindow!.SignMsg = signresponse.message; + // }); + // } + // } + // catch (Exception ex) + // { + // log.Error("注册请求发送失败", ex); + // } + // finally + // { + // log.Info("注册请求已完成"); + // } + // } public static async Task Login(bool Sign, string Username, string Userpassword) { // 公共的登录数据准备 @@ -341,7 +333,7 @@ namespace chatclient log.Error("保存登录信息到临时文件失败", ex); } } - if (MainWindow.token == null) Application.Current.Shutdown(); + if (MainWindow.UserId == null) Application.Current.Shutdown(); } } } diff --git a/chatclient/MainWindow.xaml b/chatclient/MainWindow.xaml index cf720da..bec1dd2 100644 --- a/chatclient/MainWindow.xaml +++ b/chatclient/MainWindow.xaml @@ -138,10 +138,17 @@ + - - + + + + + + + + diff --git a/chatclient/MainWindow.xaml.cs b/chatclient/MainWindow.xaml.cs index 39402fd..fbd3504 100644 --- a/chatclient/MainWindow.xaml.cs +++ b/chatclient/MainWindow.xaml.cs @@ -35,6 +35,7 @@ namespace chatclient static string? receive; public static string UserName { get; set; } = "?"; public static string? token = null; + public static string? UserId = null; private static readonly ILog log = LogManager.GetLogger(typeof(MainWindow)); public static Socket? Client; public static readonly HttpClient HttpClient = new HttpClient(); @@ -133,12 +134,13 @@ namespace chatclient var Type = JsonSerializer.Deserialize(msg); if (Type != null) { - if (Type.type == "login_1") + if (Type.type == "login") { var LoginResponse = JsonSerializer.Deserialize(msg); - if (LoginResponse!.status == "success" && LoginResponse != null) + if (LoginResponse!.status == "succeed" && LoginResponse != null) { - token = LoginResponse.token; + //token = LoginResponse.token; + UserId = LoginResponse.userid ?? "Unid"; UserName = LoginResponse.username ?? "Unnamed"; Application.Current.Dispatcher.Invoke(() => { @@ -155,7 +157,7 @@ namespace chatclient Sender = "System", MsgType = MessageType.System, Image = new BitmapImage(new Uri("pack://application:,,,/resource/user.png")), - Content = $"你好 {UserName} !", + Content = $"你好 {UserName} (id: {UserId} )!", Timestamp = DateTime.Now, Alignment = HorizontalAlignment.Center, SenderColor = new SolidColorBrush(Colors.Gray) @@ -163,7 +165,31 @@ namespace chatclient mainWindow?.Messages.Add(chatmessage); } }); - log.Info($"用户 {UserName} 登录成功(token:{token})"); + log.Info($"用户 {UserName} 登录成功(token:{token},userid:{UserId})"); + } + else if (LoginResponse!.status == "error_0") + { + log.Warn($"登录失败: {LoginResponse!.message}\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.LoginMsg = "用户名或密码错误"; + } + }); + } + else if (LoginResponse!.status == "error_2") + { + log.Warn($"登录失败: {LoginResponse!.message}\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.LoginMsg = "用户名长度必须在2到20个字符之间"; + } + }); } else { @@ -177,41 +203,68 @@ namespace chatclient }); } } - else if (Type.type == "login_0") - { - var LoginResponse = JsonSerializer.Deserialize(msg); - log.Warn($"登录失败: {LoginResponse!.message}\nMsg:{msg}"); - Application.Current.Dispatcher.Invoke(() => - { - var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); - if (loginWindow != null) - { - loginWindow.LoginMsg = "用户名或密码错误"; - } - }); - } - else if (Type.type == "register_1") + else if (Type.type == "register") { var SignResponse = JsonSerializer.Deserialize(msg); - log.Warn($"注册成功\nMsg:{msg}"); - Application.Current.Dispatcher.Invoke(async () => + if (SignResponse!.status == "success") { - //var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); - await LoginWindow.Login(true,LoginWindow.SignName, LoginWindow.SignPassword1); - }); - } - else if (Type.type == "register_0") - { - var SignResponse = JsonSerializer.Deserialize(msg); - log.Warn($"注册失败: {SignResponse!.message}\nMsg:{msg}"); - Application.Current.Dispatcher.Invoke(() => - { - var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); - if (loginWindow != null) + log.Warn($"注册成功\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(async () => { - loginWindow.SignMsg = "用户名已存在"; + //var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + await LoginWindow.Login(true, LoginWindow.SignName, LoginWindow.SignPassword1); + }); + } + else if (SignResponse!.status == "error_1") + { + log.Warn($"注册失败: {SignResponse!.message}\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.SignMsg = "密码长度必须在4到20个字符之间"; + } + }); + } + else if (SignResponse!.status == "error_2") + { + log.Warn($"注册失败: {SignResponse!.message}\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.SignMsg = "用户名长度必须在2到20个字符之间"; + } + }); + } + else if (SignResponse!.status == "error_3") + { + log.Warn($"注册失败: {SignResponse!.message}\nMsg:{msg}"); + { + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.SignMsg = "用户名已存在"; + } + }); } - }); + } + else + { + log.Error($"注册失败: {SignResponse!.message}\nMsg:{msg}"); + Application.Current.Dispatcher.Invoke(() => + { + var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); + if (loginWindow != null) + { + loginWindow.SignMsg = SignResponse != null ? SignResponse.message : "服务器返回错误"; + } + }); + } } else if (Type.type == "chat") { @@ -221,15 +274,15 @@ namespace chatclient Application.Current.Dispatcher.Invoke(() => { // 处理聊天消息 - if (chat.user == UserName) + if (chat.userid == UserId) { var chatmessage = new ChatMessage { Sender = chat.user ?? "未知用户", MsgType = MessageType.Text, - Image = new BitmapImage(new Uri(chat.image ?? "pack://application:,,,/resource/user.png", UriKind.Absolute)), + Image = new BitmapImage(new Uri(chat.avatar ?? "pack://application:,,,/resource/user.png")), Content = chat.message ?? "(无内容)", - Timestamp = DateTime.Now, + Timestamp = chat.timestamp ?? DateTime.Now, Alignment = HorizontalAlignment.Right, SenderColor = new SolidColorBrush(Colors.Blue) }; @@ -242,9 +295,9 @@ namespace chatclient { Sender = chat.user ?? "未知用户", MsgType = MessageType.Text, - Image = new BitmapImage(new Uri(chat.image ?? "pack://application:,,,/resource/user.png", UriKind.Absolute)), + Image = new BitmapImage(new Uri(chat.avatar ?? "pack://application:,,,/resource/user.png")), Content = chat.message ?? "(无内容)", - Timestamp = chat.timestamp, + Timestamp = chat.timestamp ?? DateTime.Now, Alignment = HorizontalAlignment.Left, SenderColor = new SolidColorBrush(Colors.Black) }; @@ -258,6 +311,7 @@ namespace chatclient log.Error("反序列化聊天数据时返回了 null"); } } + else if (Type.type == "ping") { } else { log.Error($"未知的消息类型: {Type.type},请检查服务器响应格式"); @@ -307,7 +361,10 @@ namespace chatclient var newChatMessage = new ChatData { type = "chat", - message = txtMessage.Text + message = txtMessage.Text, + msgtype = MessageType.Text, + userid = UserId ?? "Unid", // 使用UserId作为发送者ID + token = token // 添加当前token }; string ChatJsonData = JsonSerializer.Serialize(newChatMessage); byte[] dataBytes = Encoding.UTF8.GetBytes(ChatJsonData); @@ -372,7 +429,7 @@ namespace chatclient { log.Info("MainWindow 关闭事件触发,清理资源"); // 清理资源 - Client?.Shutdown(SocketShutdown.Both); + if (Client!.Connected) Client?.Shutdown(SocketShutdown.Both); Client?.Close(); log.Info("关闭Socket连接"); Client?.Dispose(); diff --git a/chatclient/config/log4net.config b/chatclient/config/log4net.config index 346ce4c..12dfd50 100644 --- a/chatclient/config/log4net.config +++ b/chatclient/config/log4net.config @@ -10,7 +10,7 @@ - + diff --git a/chatserver/App.config b/chatserver/App.config new file mode 100644 index 0000000..50b703a --- /dev/null +++ b/chatserver/App.config @@ -0,0 +1,7 @@ + + + +
+ + + \ No newline at end of file diff --git a/chatserver/Data/ChatData.cs b/chatserver/Data/ChatData.cs new file mode 100644 index 0000000..d8b49d2 --- /dev/null +++ b/chatserver/Data/ChatData.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace chatserver.Data +{ + public enum MessageType + { + Text, + Image,//图片 + File,//文件 + System//系统信息 + } +} diff --git a/chatserver/Data/chatapi.cs b/chatserver/Data/chatapi.cs new file mode 100644 index 0000000..5c9e194 --- /dev/null +++ b/chatserver/Data/chatapi.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace chatserver.Data +{ + internal class LoginData + { + public string? username { get; set; } = null; + public string? password { get; set; } = null; + public string? token { get; set; } = null; + } + internal class LoginResultData + { + public required string type { get; set; } = "login"; + public string? userid { get; set; } = "Unid"; + public string? status { get; set; } + public string? message { get; set; } + public string? token { get; set; } + public string? username { get; set; } + } + internal class SignData + { + public string? username { get; set; } = null; + public string? password { get; set; } = null; + } + internal class SignResultData + { + public required string type { get; set; } = "sign"; + public string? status { get; set; } = null; + public string? message { get; set; } = null; + } + internal class TypeData + { + public string? type { get; set; } + } + internal class ChatRegisterData + { + public required string type { get; set; } = "chat"; + public required string userid { get; set; } = "Unid"; + public string user { get; set; } = "Unnamed"; + public string? status { get; set; } = null; + public string? message { get; set; } = null; + public string? avatar { get; set; } = null; + public MessageType? msgtype { get; set; } = MessageType.Text; + public DateTime? timestamp { get; set; } = DateTime.Now; + } + internal class ChatData + { + public required string message { get; set; } = "message"; + public MessageType? msgtype { get; set; } = MessageType.Text; + public required string userid { get; set; } = "Unid"; + public string? token { get; set; } = null; // 添加token字段 + } +} diff --git a/chatserver/Program.cs b/chatserver/Program.cs new file mode 100644 index 0000000..650591f --- /dev/null +++ b/chatserver/Program.cs @@ -0,0 +1,264 @@ +using System.Net.Sockets; +using System.Net.Http; +using log4net; +using log4net.Config; +using System.Net; +using System.Data.SQLite; +using chatserver.Data; +using System.Text.Json; +using System.Reflection; + +[assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)] +namespace chatserver +{ + internal class ChatServer + { + private static readonly ILog log = LogManager.GetLogger(typeof(ChatServer)); + private static List Client = new(); + private static List token = new(); + private static Socket? Server; + private static SQLiteConnection? User_db; + + static void Main(string[] args) + { + //XmlConfigurator.Configure(); + log.Info("Hello World!"); + Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + Server.Bind(new IPEndPoint(IPAddress.Any, 52006)); + Server.Listen(20); + OpenUser_db(); + log.Info("服务器以在52006端口监听"); + while (true) + { + try + { + Socket client = Server.Accept(); + Client.Add(client); + log.Info($"用户{client.RemoteEndPoint}连接"); + Thread thread = new Thread(() => HandleClient(client)); + thread.Start(); + } + catch (Exception ex) + { + log.Error("Error accepting client connection: " + ex.Message); + } + } + } + public static void OpenUser_db() + { + log.Info("正在打开数据库连接..."); + User_db = new SQLiteConnection("Data Source=ServerUser.db;Version=3;"); //没有数据库则自动创建 + User_db.Open(); + EnsureUsersTableExists(); // 确保users表存在 + log.Info("数据库连接已打开"); + } + static void HandleClient(Socket socket) + { + try + { + while (true) + + { + byte[] buffer = new byte[1024]; + int received = socket.Receive(buffer); + if (received == 0) break; // 客户端断开连接 + string message = System.Text.Encoding.UTF8.GetString(buffer, 0, received); + log.Info("Received message: " + message); + var Type = JsonSerializer.Deserialize(message); + if (Type != null) + { + if (Type.type == "register") + { + var sginuser = JsonSerializer.Deserialize(message); + if (sginuser != null && sginuser.username != null && sginuser.password != null) + { + log.Info($"用户 {sginuser.username} 正在注册"); + if (string.IsNullOrEmpty(sginuser.username) || string.IsNullOrEmpty(sginuser.password)) + { + log.Warn("用户名或密码不能为空"); + var emptyResult = new SignResultData { type = "register", status = "error_-1", message = "用户名或密码不能为空" }; + socket.Send(JsonSerializer.SerializeToUtf8Bytes(emptyResult)); + continue; // 如果用户名或密码为空,则跳过注册流程 + } + if (sginuser.username.Length < 2 || sginuser.username.Length > 20) + { + log.Warn($"用户注册时 {sginuser.username} 用户名长度不符合要求"); + var lengthResult = new SignResultData { type = "register", status = "error_2", message = "用户名长度必须在2到20个字符之间" }; + socket.Send(JsonSerializer.SerializeToUtf8Bytes(lengthResult)); + continue; // 如果用户名长度不符合要求,则跳过注册流程 + } + if (sginuser.password.Length < 4 || sginuser.password.Length > 20) + { + log.Warn($"用户注册时 {sginuser.username} 密码长度不符合要求"); + var weakPwdResult = new SignResultData { type = "register", status = "error_1", message = "密码长度必须在4到20个字符之间" }; + socket.Send(JsonSerializer.SerializeToUtf8Bytes(weakPwdResult)); + continue; // 如果密码过弱,则跳过注册流程 + } + if (UserExists(sginuser.username)) + { + log.Warn($"用户 {sginuser.username} 已存在"); + var Result = new SignResultData { type = "register", status = "error_0", message = "用户名已存在" }; + socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Result))); + continue;// 如果用户名已存在,则跳过注册流程 + } + var cmd = new SQLiteCommand("INSERT INTO users (userid, username, password) VALUES (@userid, @username, @password)", User_db); + var timedUlid = Ulid.NewUlid(DateTimeOffset.UtcNow); + cmd.Parameters.AddWithValue("@userid", timedUlid); + cmd.Parameters.AddWithValue("@username", sginuser.username); + cmd.Parameters.AddWithValue("@password", sginuser.password); + cmd.ExecuteNonQuery(); + log.Info($"用户 {sginuser.username} 注册成功(id:{timedUlid})"); + var result = new SignResultData { type = "register", status = "succeed", message = "注册成功" }; + socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result))); + } + } + else if (Type.type == "login") + { + var loginData = JsonSerializer.Deserialize(message); + if (loginData != null) + { + if (string.IsNullOrEmpty(loginData.username) || string.IsNullOrEmpty(loginData.password)) + { + log.Warn("用户名或密码不能为空"); + var emptyResult = new LoginResultData { type = "login", status = "error_-1", message = "用户名或密码不能为空" }; + socket.Send(JsonSerializer.SerializeToUtf8Bytes(emptyResult)); + continue; // 如果用户名或密码为空,则跳过登录流程 + } + if (loginData.username.Length < 2 || loginData.username.Length > 20) + { + log.Warn($"用户登录时 {loginData.username} 用户名长度不符合要求"); + var lengthResult = new LoginResultData { type = "login", status = "error_2", message = "用户名长度必须在2到20个字符之间" }; + socket.Send(JsonSerializer.SerializeToUtf8Bytes(lengthResult)); + continue; // 如果用户名长度不符合要求,则跳过登录流程 + } + var Authentication = UserAuthentication(loginData.username, loginData.password); + if (Authentication != "") + { + log.Info($"用户 {loginData.username} 登录成功 (id:{Authentication})"); + var result = new LoginResultData + { + type = "login", + status = "succeed", + message = "登录成功", + //token = Authentication, + username = loginData.username, + userid = Authentication + }; + socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result))); + } + else + { + log.Warn($"用户 {loginData.username} 登录失败,用户名或密码错误"); + var result = new LoginResultData { type = "login", status = "error_0", message = "用户名或密码错误" }; + socket.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(result))); + } + } + } + else if (Type.type == "chat") + { + var chatData = JsonSerializer.Deserialize(message); + if (chatData != null && chatData.message != null) + { + log.Info($"接收到聊天消息: {chatData.message}"); + var chatRegisterData = new ChatRegisterData + { + type = "chat", + userid = chatData.userid ?? "Unid", + user = GetUsernameByUserId(chatData.userid!), + message = chatData.message, + msgtype = chatData.msgtype ?? MessageType.Text, + // 替换为 + timestamp = DateTime.Now + }; + foreach (var client in Client) + { + client.Send(System.Text.Encoding.UTF8.GetBytes(JsonSerializer.Serialize(chatRegisterData))); + } + } + else + { + log.Warn("接收到无效的聊天消息"); + } + } + else + { + log.Warn("未知的请求类型: " + Type.type); + } + } + } + } + catch (SocketException ex) + { + log.Error("Socket error: " + ex.Message); + } + catch (JsonException ex) + { + log.Error("JSON parsing error: " + ex.Message); + } + catch (Exception ex) + { + log.Error("Error handling client: " + ex.Message); + } + finally + { + log.Info($"用户{socket.RemoteEndPoint}已断开连接"); + socket.Close(); + Client.Remove(socket); + } + } + /// + /// 查询User_db是否有相同用户名 + /// + /// + /// + static bool UserExists(string username) + { + using var cmd = new SQLiteCommand("SELECT COUNT(*) FROM users WHERE username = @username", User_db); + cmd.Parameters.AddWithValue("@username", username); + var count = Convert.ToInt32(cmd.ExecuteScalar()); + return count > 0; + } + /// + /// 验证用户登录信息并返回userid结果 + /// + /// + /// + /// + static string UserAuthentication(string username, string password) + { + using var cmd = new SQLiteCommand("SELECT userid FROM users WHERE username = @username AND password = @password", User_db); + cmd.Parameters.AddWithValue("@username", username); + cmd.Parameters.AddWithValue("@password", password); + var result = cmd.ExecuteScalar(); + return result != null ? result.ToString()! : string.Empty; + } + // 在ChatServer类中添加一个方法用于初始化users表 + private static void EnsureUsersTableExists() + { + using var cmd = new SQLiteCommand(@" + CREATE TABLE IF NOT EXISTS users ( + userid TEXT PRIMARY KEY, + username TEXT NOT NULL UNIQUE, + password TEXT NOT NULL + )", User_db); + cmd.ExecuteNonQuery(); + } + /// + /// 根据userid查询对应的用户名 + /// + /// + /// 用户名,如果不存在则返回 + static string GetUsernameByUserId(string userid) + { + if (string.IsNullOrEmpty(userid) || userid == "Unid") + { + return "Unnamed"; // 如果userid为空或为"Unid",返回默认用户名 + } + using var cmd = new SQLiteCommand("SELECT username FROM users WHERE userid = @userid", User_db); + cmd.Parameters.AddWithValue("@userid", userid); + var result = cmd.ExecuteScalar(); + return result != null ? result.ToString()! : "Unnamed"; + } + + } +} \ No newline at end of file diff --git a/chatserver/Properties/launchSettings.json b/chatserver/Properties/launchSettings.json new file mode 100644 index 0000000..f19cb4e --- /dev/null +++ b/chatserver/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "chatserver": { + "commandName": "Project", + "sqlDebugging": false + } + } +} \ No newline at end of file diff --git a/chatserver/chatserver.csproj b/chatserver/chatserver.csproj new file mode 100644 index 0000000..21e5310 --- /dev/null +++ b/chatserver/chatserver.csproj @@ -0,0 +1,26 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + PreserveNewest + + + + + + + + + + diff --git a/chatserver/config/log4net.config b/chatserver/config/log4net.config new file mode 100644 index 0000000..ab28e9f --- /dev/null +++ b/chatserver/config/log4net.config @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file