using System; using System.Net.Sockets; using System.Text; using System.Threading; using Newtonsoft.Json; namespace NoticeServer { /// /// 연결된 채팅 클라이언트 정보 및 통신 관리 /// public class ChatClient { private TcpClient tcpClient; private NetworkStream stream; private Thread receiveThread; private bool isConnected; /// 클라이언트 고유 ID public string ClientId { get; private set; } /// 닉네임 public string NickName { get; set; } /// 사원번호 (Employee ID) public string EmployeeId { get; set; } /// 사용자 그룹 public string UserGroup { get; set; } /// IP 주소 public string IpAddress { get; private set; } /// 호스트명 public string HostName { get; set; } /// 연결 시간 public DateTime ConnectedTime { get; private set; } /// 마지막 활동 시간 public DateTime LastActivity { get; set; } /// 메시지 수신 이벤트 public event EventHandler MessageReceived; /// 연결 해제 이벤트 public event EventHandler Disconnected; public ChatClient(TcpClient client) { tcpClient = client; stream = client.GetStream(); isConnected = true; ClientId = Guid.NewGuid().ToString(); ConnectedTime = DateTime.Now; LastActivity = DateTime.Now; var endpoint = client.Client.RemoteEndPoint.ToString(); IpAddress = endpoint.Split(':')[0]; StartReceiving(); } /// /// 메시지 수신 스레드 시작 /// private void StartReceiving() { receiveThread = new Thread(ReceiveLoop) { IsBackground = true, Name = $"ChatClient-{ClientId}" }; receiveThread.Start(); } /// /// 메시지 수신 루프 /// private void ReceiveLoop() { byte[] buffer = new byte[4096]; try { while (isConnected && tcpClient.Connected) { int bytesRead = stream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) { // Connection closed break; } string jsonData = Encoding.UTF8.GetString(buffer, 0, bytesRead); var message = JsonConvert.DeserializeObject(jsonData); if (message != null) { LastActivity = DateTime.Now; // Set nickname, employeeId, userGroup from Connect message if (message.Type == MessageType.Connect && !string.IsNullOrEmpty(message.NickName)) { NickName = message.NickName; EmployeeId = message.EmployeeId; UserGroup = message.UserGroup; HostName = message.HostName; } MessageReceived?.Invoke(this, message); } } } catch (Exception ex) { Console.WriteLine($"[ERROR] Client {NickName ?? ClientId} receive error: {ex.Message}"); } finally { Disconnect(); } } /// /// Send message /// public bool SendMessage(ChatMessage message) { if (!isConnected || !tcpClient.Connected) return false; try { string jsonData = JsonConvert.SerializeObject(message); byte[] data = Encoding.UTF8.GetBytes(jsonData); stream.Write(data, 0, data.Length); stream.Flush(); return true; } catch (Exception ex) { Console.WriteLine($"[ERROR] Client {NickName ?? ClientId} send error: {ex.Message}"); Disconnect(); return false; } } /// /// 연결 해제 /// public void Disconnect() { if (!isConnected) return; isConnected = false; try { stream?.Close(); tcpClient?.Close(); } catch { } Disconnected?.Invoke(this, ClientId); } public override string ToString() { return $"{NickName ?? "Unknown"} ({IpAddress})"; } } }