using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Net.Sockets;//socket库 using System.Net.Http; using System.Net; using System.IO; using System; using System.Security.Policy; using log4net; using log4net.Config; using System.Text.Json; using chatclient.Data; using System.ComponentModel; using System.Collections.ObjectModel; using System.Windows.Threading; using System.Collections.Specialized; [assembly: XmlConfigurator(ConfigFile = "config/log4net.config", Watch = true)] namespace chatclient { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window, INotifyPropertyChanged { LoginWindow Login = new(); static string? receive; public static string UserName { get; set; } = "?"; public static string? token = null; private static readonly ILog log = LogManager.GetLogger(typeof(MainWindow)); public static Socket? Client; public static readonly HttpClient HttpClient = new HttpClient(); public event PropertyChangedEventHandler? PropertyChanged; private string? _Username; public string? Username { get { return _Username; } set { _Username = value; Update("Username"); } } // 消息列表 public ObservableCollection Messages { get; } = new ObservableCollection(); private ItemsControl MessageList => messageList; private ScrollViewer MessageScroller => messageScroller; private void Update(string UpdateName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(UpdateName)); } public MainWindow() { InitializeComponent(); this.DataContext = this; log.Info("Hello World!"); this.Hide(); Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { log.Info($"连接服务器 {Server.ServerIP}:{Server.ServerPort} "); Client.Connect(Server.ServerIP, Server.ServerPort); } catch (Exception ex) { Client.Close(); log.Error(ex); } Login.Show(); if(Client != null && Client.Connected == true) StartReceive(); MessageList.ItemsSource = Messages; ((INotifyCollectionChanged)MessageList.Items).CollectionChanged += (s, e) => { // 确保有足够的时间让UI更新 Dispatcher.BeginInvoke(new Action(() => { MessageScroller.ScrollToEnd(); }), DispatcherPriority.ContextIdle); }; } public static void StartReceive() { if (Client != null && Client.Connected == true) { Thread th = new Thread(Receive); th.Start(); } else { log.Fatal("在Client为NULL或未连接服务器时被调用StartReceive()"); } } static void Receive() { byte[] buffer = new byte[1024]; try { while (true) { int num = Client!.Receive(buffer); if (num == 0) break; if (Client.Poll(100, SelectMode.SelectRead) && Client.Available == 0 || !Client.Connected) { log.Error("连接已断开"); break; } receive = Encoding.UTF8.GetString(buffer, 0, num); response(receive); } } catch (Exception ex) { log.Error(ex); } finally { Client?.Close(); } } static void response(string msg) { log.Info($"收到服务器消息: {msg}"); try { var Type = JsonSerializer.Deserialize(msg); if (Type != null) { var LoginResponse = JsonSerializer.Deserialize(msg); if (Type.type == "login_1") { if (LoginResponse!.status == "success" && LoginResponse != null) { token = LoginResponse.token; Application.Current.Dispatcher.Invoke(() => { var mainWindow = Application.Current.Windows.OfType().FirstOrDefault(); if (mainWindow != null) { mainWindow.Username = UserName; mainWindow.Show(); var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); loginWindow?.Close(); mainWindow.Activate(); } }); log.Info($"用户 {UserName} 登录成功(token:{token})"); } else { Application.Current.Dispatcher.Invoke(() => { var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); if (loginWindow != null) { loginWindow.LoginMsg = LoginResponse != null ? LoginResponse.message : "服务器返回错误"; } }); } } else if (Type.type == "login_0" && LoginResponse != null) { 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 == "chat") { var chat = JsonSerializer.Deserialize(msg); if (chat != null) { Application.Current.Dispatcher.Invoke(() => { // 处理聊天消息 var chatmessage = new ChatMessage { Sender = chat.user ?? "未知用户", Type = MessageType.Text, Image = new BitmapImage(new Uri(chat.image ?? "pack://application:,,,/resource/user.png", UriKind.Absolute)), Content = chat.message ?? "无内容", Timestamp = chat.timestamp, Alignment = HorizontalAlignment.Left, SenderColor = new SolidColorBrush(Colors.Black) }; var mainWindow = Application.Current.Windows.OfType().FirstOrDefault(); mainWindow?.Messages.Add(chatmessage); }); } else { log.Error("反序列化聊天数据时返回了 null"); } } else { log.Error($"未知的消息类型: {Type.type},请检查服务器响应格式"); Application.Current.Dispatcher.Invoke(() => { var loginWindow = Application.Current.Windows.OfType().FirstOrDefault(); if (loginWindow != null) loginWindow.LoginMsg = "服务器返回了错误的值"; }); } } } catch (JsonException ex) { log.Error("JSON解析错误", ex); } catch (Exception ex) { log.Error("处理响应时发生错误", ex); } } private void SendMessage_Click(object sender, RoutedEventArgs e) { SendMessage(); } private void SendMessage() { if (string.IsNullOrWhiteSpace(txtMessage.Text)) return; // 获取当前选中的联系人 //var contact = cmbContacts.SelectedItem as Contact; // 判断是否为群组,若是则收件人设为“所有人”,否则为联系人显示名 //string recipient = contact?.IsGroup == true ? "所有人" : contact?.DisplayName; // 创建新消息 var newMessage = new ChatMessage { Sender = "我", Type = MessageType.Text, Image = new BitmapImage(new Uri("pack://application:,,,/resource/user.png", UriKind.Absolute)), // 默认头像 Content = txtMessage.Text, Timestamp = DateTime.Now, Alignment = HorizontalAlignment.Right, // 自己发送的消息靠右 SenderColor = new SolidColorBrush(Colors.Blue) }; var newChatMessage = new ChatData { type = "chat", message = newMessage.Content }; string ChatJsonData = JsonSerializer.Serialize(newChatMessage); byte[] dataBytes = Encoding.UTF8.GetBytes(ChatJsonData); log.Info($"向服务器聊天信息(长度:{dataBytes.Length})"); if (Client != null) { if (Client.Connected) { Client.Send(dataBytes); } else { try { log.Info("未连接服务器,尝试连接"); Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Client.Connect(IPAddress.Parse(Server.ServerIP), Server.ServerPort); } catch (Exception ex) { log.Error(ex); Client.Close(); } //finally //{ // //} } } // 添加到消息列表 Messages.Add(newMessage); // 清空输入框 txtMessage.Clear(); } } }