From a8be3eb3a4f3393840078d7c5b349e72a239e039 Mon Sep 17 00:00:00 2001 From: syneffort Date: Fri, 3 Mar 2023 11:27:48 +0900 Subject: [PATCH] chat function --- Chat/Client/ChatRoomForm.cs | 23 ++++++++++-- Chat/Client/LoginForm.cs | 1 + Chat/Client/Singleton.cs | 6 +++ Chat/Core/ChatPacket.cs | 74 +++++++++++++++++++++++++++++++++++++ Chat/Core/PServer.cs | 16 +++++++- Chat/Core/PacketType.cs | 1 + 6 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 Chat/Core/ChatPacket.cs diff --git a/Chat/Client/ChatRoomForm.cs b/Chat/Client/ChatRoomForm.cs index 6aaa874..6985441 100644 --- a/Chat/Client/ChatRoomForm.cs +++ b/Chat/Client/ChatRoomForm.cs @@ -25,17 +25,18 @@ namespace Client lbxUser.Items.Add(Singleton.Instance.Nickname); Singleton.Instance.UserEnterResponsed += UserEnterResponsed; Singleton.Instance.UserLeaveResponsed += UserLeaveResponsed; + Singleton.Instance.ChatResponsed += ChatResponsed; } - private void btmSend_Click(object sender, EventArgs e) + private async void btmSend_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(tbxMsg.Text)) return; - lbxMsg.Items.Add(tbxMsg.Text); - tbxMsg.Text = null; + ChatPacket packet = new ChatPacket(Singleton.Instance.Nickname, tbxMsg.Text); + await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None); - ScrollMsgToEnd(); + tbxMsg.Text = null; } private void ScrollMsgToEnd() @@ -83,10 +84,24 @@ namespace Client }); } + private void ChatResponsed(object? sender, EventArgs e) + { + if (sender == null) + return; + + ChatPacket packet = (ChatPacket)sender; + InvokeMethod(() => + { + lbxMsg.Items.Add($"{packet.NickName}: {packet.Message}"); + ScrollMsgToEnd(); + }); + } + private async void ChatRoomForm_FormClosing(object sender, FormClosingEventArgs e) { Singleton.Instance.UserEnterResponsed -= UserEnterResponsed; Singleton.Instance.UserLeaveResponsed -= UserLeaveResponsed; + Singleton.Instance.ChatResponsed -= ChatResponsed; UserLeavePacket packet = new UserLeavePacket(Singleton.Instance.Nickname); await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None); diff --git a/Chat/Client/LoginForm.cs b/Chat/Client/LoginForm.cs index 1712592..ba6f487 100644 --- a/Chat/Client/LoginForm.cs +++ b/Chat/Client/LoginForm.cs @@ -60,6 +60,7 @@ namespace Client else { Singleton.Instance.Socket.Shutdown(SocketShutdown.Send); + MessageBox.Show("Fail to login"); } } } diff --git a/Chat/Client/Singleton.cs b/Chat/Client/Singleton.cs index 40a1957..b6fbbe5 100644 --- a/Chat/Client/Singleton.cs +++ b/Chat/Client/Singleton.cs @@ -23,6 +23,7 @@ namespace Client public event EventHandler? EnterRoomResponsed; public event EventHandler? UserEnterResponsed; public event EventHandler? UserLeaveResponsed; + public event EventHandler? ChatResponsed; public async Task ConnectAsync(string ip, int port) { @@ -100,6 +101,11 @@ namespace Client UserLeavePacket packet = new UserLeavePacket(dataBuffer); UserLeaveResponsed?.Invoke(packet, EventArgs.Empty); } + else if (packetType == PacketType.Chat) + { + ChatPacket packet = new ChatPacket(dataBuffer); + ChatResponsed?.Invoke(packet, EventArgs.Empty); + } } } } diff --git a/Chat/Core/ChatPacket.cs b/Chat/Core/ChatPacket.cs new file mode 100644 index 0000000..122d59c --- /dev/null +++ b/Chat/Core/ChatPacket.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace Core +{ + public class ChatPacket : IPacket + { + public string Message { get; private set; } + public string NickName { get; private set; } + + public ChatPacket(string nickname, string message) + { + NickName = nickname; + Message = message; + } + + public ChatPacket(byte[] buffer) + { + int cursor = 2; + + short messageSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor)); + cursor += sizeof(short); + + Message = Encoding.UTF8.GetString(buffer, cursor, messageSize); + cursor += messageSize; + + short nicknameSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor)); + cursor += sizeof(short); + + NickName = Encoding.UTF8.GetString(buffer, cursor, nicknameSize); + } + + public byte[] Serialize() + { + // 2bytes header + // data: 2bytes packetType + 2bytes id size + id + 2bytes nickname size + nickname + + byte[] packetType = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)PacketType.Chat)); + byte[] message = Encoding.UTF8.GetBytes(Message); + byte[] messageSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)message.Length)); + byte[] nickname = Encoding.UTF8.GetBytes(NickName); + byte[] nicknameSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)nickname.Length)); + + short dataSize = (short)(packetType.Length + message.Length + messageSize.Length + nickname.Length + nicknameSize.Length); + byte[] header = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(dataSize)); + + byte[] buffer = new byte[2 + dataSize]; + + int cursor = 0; + Array.Copy(header, 0, buffer, cursor, header.Length); + cursor += header.Length; + + Array.Copy(packetType, 0, buffer, cursor, packetType.Length); + cursor += packetType.Length; + + Array.Copy(messageSize, 0, buffer, cursor, messageSize.Length); + cursor += messageSize.Length; + + Array.Copy(message, 0, buffer, cursor, message.Length); + cursor += message.Length; + + Array.Copy(nicknameSize, 0, buffer, cursor, nicknameSize.Length); + cursor += nicknameSize.Length; + + Array.Copy(nickname, 0, buffer, cursor, nickname.Length); + + return buffer; + } + } +} diff --git a/Chat/Core/PServer.cs b/Chat/Core/PServer.cs index 1accb62..1c046b6 100644 --- a/Chat/Core/PServer.cs +++ b/Chat/Core/PServer.cs @@ -76,13 +76,13 @@ namespace Core { LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer); - Clients.TryAdd(requestPacket.Id, clientSocket); + bool result = Clients.TryAdd(requestPacket.Id, clientSocket); Console.WriteLine($"[{DateTime.Now}] LoginRequest - Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}"); id = requestPacket.Id; nickname = requestPacket.NickName; - LoginResponsePacket responsePacket = new LoginResponsePacket(StatusCode.Success); + LoginResponsePacket responsePacket = new LoginResponsePacket(result ? StatusCode.Success : StatusCode.Failed); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); } else if (packetType == PacketType.CreateRoomRequest) @@ -169,6 +169,18 @@ namespace Core } } } + else if (packetType == PacketType.Chat) + { + ChatPacket packet = new ChatPacket(dataBuffer); + if (Rooms.TryGetValue(roomName, out var room)) + { + foreach (var user in room.Users) + { + if (Clients.TryGetValue(user.Key, out var otherClient)) + await otherClient.SendAsync(packet.Serialize(), SocketFlags.None); + } + } + } } } } diff --git a/Chat/Core/PacketType.cs b/Chat/Core/PacketType.cs index cd37c0f..d1be89e 100644 --- a/Chat/Core/PacketType.cs +++ b/Chat/Core/PacketType.cs @@ -18,5 +18,6 @@ namespace Core EnterRoomResponse, UserEnter, UserLeave, + Chat } }