Files
Groupware/SubProject/ChatServer/ChatClient.cs
2025-11-12 13:57:13 +09:00

175 lines
5.1 KiB
C#

using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
namespace NoticeServer
{
/// <summary>
/// 연결된 채팅 클라이언트 정보 및 통신 관리
/// </summary>
public class ChatClient
{
private TcpClient tcpClient;
private NetworkStream stream;
private Thread receiveThread;
private bool isConnected;
/// <summary>클라이언트 고유 ID</summary>
public string ClientId { get; private set; }
/// <summary>닉네임</summary>
public string NickName { get; set; }
/// <summary>사원번호 (Employee ID)</summary>
public string EmployeeId { get; set; }
/// <summary>사용자 그룹</summary>
public string UserGroup { get; set; }
/// <summary>IP 주소</summary>
public string IpAddress { get; private set; }
/// <summary>호스트명</summary>
public string HostName { get; set; }
/// <summary>연결 시간</summary>
public DateTime ConnectedTime { get; private set; }
/// <summary>마지막 활동 시간</summary>
public DateTime LastActivity { get; set; }
/// <summary>메시지 수신 이벤트</summary>
public event EventHandler<ChatMessage> MessageReceived;
/// <summary>연결 해제 이벤트</summary>
public event EventHandler<string> 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();
}
/// <summary>
/// 메시지 수신 스레드 시작
/// </summary>
private void StartReceiving()
{
receiveThread = new Thread(ReceiveLoop)
{
IsBackground = true,
Name = $"ChatClient-{ClientId}"
};
receiveThread.Start();
}
/// <summary>
/// 메시지 수신 루프
/// </summary>
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<ChatMessage>(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();
}
}
/// <summary>
/// Send message
/// </summary>
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;
}
}
/// <summary>
/// 연결 해제
/// </summary>
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})";
}
}
}