user enter, leave

main
syneffort 2 years ago
parent c4451759f7
commit a754ba2956
  1. 1
      Chat/Client/ChatRoomForm.Designer.cs
  2. 60
      Chat/Client/ChatRoomForm.cs
  3. 8
      Chat/Client/RoomListForm.cs
  4. 12
      Chat/Client/Singleton.cs
  5. 42
      Chat/Core/PServer.cs
  6. 58
      Chat/Core/UserEnterPacket.cs
  7. 58
      Chat/Core/UserLeavePacket.cs

@ -84,6 +84,7 @@
this.Name = "ChatRoomForm"; this.Name = "ChatRoomForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "CharRoomForm"; this.Text = "CharRoomForm";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ChatRoomForm_FormClosing);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();

@ -1,9 +1,11 @@
using System; using Core;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data; using System.Data;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@ -15,6 +17,14 @@ namespace Client
public ChatRoomForm() public ChatRoomForm()
{ {
InitializeComponent(); InitializeComponent();
InitInstance();
}
private void InitInstance()
{
lbxUser.Items.Add(Singleton.Instance.Nickname);
Singleton.Instance.UserEnterResponsed += UserEnterResponsed;
Singleton.Instance.UserLeaveResponsed += UserLeaveResponsed;
} }
private void btmSend_Click(object sender, EventArgs e) private void btmSend_Click(object sender, EventArgs e)
@ -33,5 +43,53 @@ namespace Client
lbxMsg.SelectedIndex = lbxMsg.Items.Count - 1; lbxMsg.SelectedIndex = lbxMsg.Items.Count - 1;
lbxMsg.SelectedIndex = -1; lbxMsg.SelectedIndex = -1;
} }
private void InvokeMethod(InvokedMethod method)
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(() =>
{
method();
}));
}
else
{
method();
}
}
private void UserEnterResponsed(object? sender, EventArgs e)
{
if (sender == null)
return;
UserEnterPacket packet = (UserEnterPacket)sender;
InvokeMethod(() =>
{
lbxUser.Items.Add(packet.Nickname);
});
}
private void UserLeaveResponsed(object? sender, EventArgs e)
{
if (sender == null)
return;
UserLeavePacket packet = (UserLeavePacket)sender;
InvokeMethod(() =>
{
lbxUser.Items.Remove(packet.Nickname);
});
}
private async void ChatRoomForm_FormClosing(object sender, FormClosingEventArgs e)
{
Singleton.Instance.UserEnterResponsed -= UserEnterResponsed;
Singleton.Instance.UserLeaveResponsed -= UserLeaveResponsed;
UserLeavePacket packet = new UserLeavePacket(Singleton.Instance.Nickname);
await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None);
}
} }
} }

@ -12,10 +12,10 @@ using System.Windows.Forms;
namespace Client namespace Client
{ {
delegate void InvokedMethod();
public partial class RoomListForm : Form public partial class RoomListForm : Form
{ {
private delegate void InvokedMethod();
public RoomListForm() public RoomListForm()
{ {
InitializeComponent(); InitializeComponent();
@ -61,9 +61,9 @@ namespace Client
private void InvokeMethod(InvokedMethod method) private void InvokeMethod(InvokedMethod method)
{ {
if (InvokeRequired) if (this.InvokeRequired)
{ {
lbxRoom.Invoke(new MethodInvoker(() => this.Invoke(new MethodInvoker(() =>
{ {
method(); method();
})); }));

@ -21,6 +21,8 @@ namespace Client
public event EventHandler? CreateRoomResponsed; public event EventHandler? CreateRoomResponsed;
public event EventHandler? RoomListResponsed; public event EventHandler? RoomListResponsed;
public event EventHandler? EnterRoomResponsed; public event EventHandler? EnterRoomResponsed;
public event EventHandler? UserEnterResponsed;
public event EventHandler? UserLeaveResponsed;
public async Task ConnectAsync(string ip, int port) public async Task ConnectAsync(string ip, int port)
{ {
@ -88,6 +90,16 @@ namespace Client
EnterRoomResponsePacket packet = new EnterRoomResponsePacket(dataBuffer); EnterRoomResponsePacket packet = new EnterRoomResponsePacket(dataBuffer);
EnterRoomResponsed?.Invoke(packet, EventArgs.Empty); EnterRoomResponsed?.Invoke(packet, EventArgs.Empty);
} }
else if (packetType == PacketType.UserEnter)
{
UserEnterPacket packet = new UserEnterPacket(dataBuffer);
UserEnterResponsed?.Invoke(packet, EventArgs.Empty);
}
else if (packetType == PacketType.UserLeave)
{
UserLeavePacket packet = new UserLeavePacket(dataBuffer);
UserLeaveResponsed?.Invoke(packet, EventArgs.Empty);
}
} }
} }
} }

@ -13,7 +13,8 @@ namespace Core
{ {
private Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); private Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private ConcurrentDictionary<string, Room> Rooms { get; } = new ConcurrentDictionary<string, Room>(); public ConcurrentDictionary<string, Room> Rooms { get; } = new ConcurrentDictionary<string, Room>();
public ConcurrentDictionary<string, Socket> Clients { get; } = new ConcurrentDictionary<string, Socket>();
public PServer(string ip, int port, int backlog) public PServer(string ip, int port, int backlog)
{ {
@ -74,6 +75,8 @@ namespace Core
if (packetType == PacketType.LoginRequest) if (packetType == PacketType.LoginRequest)
{ {
LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer); LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer);
Clients.TryAdd(requestPacket.Id, clientSocket);
Console.WriteLine($"[{DateTime.Now}] LoginRequest - Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}"); Console.WriteLine($"[{DateTime.Now}] LoginRequest - Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}");
id = requestPacket.Id; id = requestPacket.Id;
@ -119,6 +122,24 @@ namespace Core
EnterRoomResponsePacket responsePacket = new EnterRoomResponsePacket(StatusCode.Success); EnterRoomResponsePacket responsePacket = new EnterRoomResponsePacket(StatusCode.Success);
await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None);
await Task.Delay(100);
foreach (var user in room.Users)
{
if (user.Value == nickname)
continue;
// add me to other user
if (Clients.TryGetValue(user.Key, out var otherClient))
{
UserEnterPacket enterPacket = new UserEnterPacket(nickname);
await otherClient.SendAsync(enterPacket.Serialize(), SocketFlags.None);
}
// add other user to me
UserEnterPacket packet = new UserEnterPacket(user.Value);
await clientSocket.SendAsync(packet.Serialize(), SocketFlags.None);
}
} }
else else
{ {
@ -129,6 +150,25 @@ namespace Core
} }
} }
else if (packetType == PacketType.UserLeave)
{
UserLeavePacket packet = new UserLeavePacket(dataBuffer);
if (Rooms.TryGetValue(roomName, out var room))
{
room.Users.TryRemove(id, out _);
if (room.Users.IsEmpty)
Rooms.TryRemove(roomName, out _);
roomName = "";
foreach (var user in room.Users)
{
if (Clients.TryGetValue(user.Key, out var otherClient))
await otherClient.SendAsync(packet.Serialize(), SocketFlags.None);
}
}
}
} }
} }
} }

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class UserEnterPacket : IPacket
{
public string Nickname { get; private set; }
public UserEnterPacket(string nickname)
{
Nickname = nickname;
}
public UserEnterPacket(byte[] buffer)
{
int cursor = 2;
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.UserEnter));
byte[] roomName = Encoding.UTF8.GetBytes(Nickname);
byte[] roomNameSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)roomName.Length));
short dataSize = (short)(packetType.Length + roomName.Length + roomNameSize.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(roomNameSize, 0, buffer, cursor, roomNameSize.Length);
cursor += roomNameSize.Length;
Array.Copy(roomName, 0, buffer, cursor, roomName.Length);
return buffer;
}
}
}

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class UserLeavePacket : IPacket
{
public string Nickname { get; private set; }
public UserLeavePacket(string nickname)
{
Nickname = nickname;
}
public UserLeavePacket(byte[] buffer)
{
int cursor = 2;
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.UserLeave));
byte[] roomName = Encoding.UTF8.GetBytes(Nickname);
byte[] roomNameSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)roomName.Length));
short dataSize = (short)(packetType.Length + roomName.Length + roomNameSize.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(roomNameSize, 0, buffer, cursor, roomNameSize.Length);
cursor += roomNameSize.Length;
Array.Copy(roomName, 0, buffer, cursor, roomName.Length);
return buffer;
}
}
}
Loading…
Cancel
Save