create room, get room information from server

main
syneffort 2 years ago
parent 3230581fb5
commit 09cce59aa2
  1. 12
      Chat/Client/LoginForm.cs
  2. 20
      Chat/Client/RoomListForm.Designer.cs
  3. 101
      Chat/Client/RoomListForm.cs
  4. 12
      Chat/Client/Singleton.cs
  5. 58
      Chat/Core/CreateRoomRequestPacket.cs
  6. 49
      Chat/Core/CreateRoomResponsePacket.cs
  7. 40
      Chat/Core/PServer.cs
  8. 4
      Chat/Core/PacketType.cs
  9. 14
      Chat/Core/Room.cs
  10. 30
      Chat/Core/RoomListRequestPacket.cs
  11. 68
      Chat/Core/RoomListResponsePacket.cs
  12. 1
      Chat/Core/StatusCode.cs

@ -47,11 +47,15 @@ namespace Client
return; return;
LoginResponsePacket packet = (LoginResponsePacket)sender; LoginResponsePacket packet = (LoginResponsePacket)sender;
MessageBox.Show(packet.Code.ToString()); if (packet.Code == StatusCode.Success)
if (packet.Code != StatusCode.Success)
{ {
RoomListForm roomListForm = new RoomListForm(); IAsyncResult ar = null;
roomListForm.ShowDialog(); ar = BeginInvoke(() =>
{
RoomListForm roomListForm = new RoomListForm();
roomListForm.ShowDialog();
EndInvoke(ar);
});
} }
else else
{ {

@ -34,20 +34,21 @@
this.btnCreate = new System.Windows.Forms.Button(); this.btnCreate = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.btnRefresh = new System.Windows.Forms.Button();
this.SuspendLayout(); this.SuspendLayout();
// //
// lbxRoom // lbxRoom
// //
this.lbxRoom.FormattingEnabled = true; this.lbxRoom.FormattingEnabled = true;
this.lbxRoom.ItemHeight = 15; this.lbxRoom.ItemHeight = 15;
this.lbxRoom.Location = new System.Drawing.Point(12, 27); this.lbxRoom.Location = new System.Drawing.Point(12, 31);
this.lbxRoom.Name = "lbxRoom"; this.lbxRoom.Name = "lbxRoom";
this.lbxRoom.Size = new System.Drawing.Size(180, 214); this.lbxRoom.Size = new System.Drawing.Size(180, 214);
this.lbxRoom.TabIndex = 0; this.lbxRoom.TabIndex = 0;
// //
// btnEnter // btnEnter
// //
this.btnEnter.Location = new System.Drawing.Point(12, 247); this.btnEnter.Location = new System.Drawing.Point(12, 251);
this.btnEnter.Name = "btnEnter"; this.btnEnter.Name = "btnEnter";
this.btnEnter.Size = new System.Drawing.Size(180, 23); this.btnEnter.Size = new System.Drawing.Size(180, 23);
this.btnEnter.TabIndex = 1; this.btnEnter.TabIndex = 1;
@ -75,7 +76,7 @@
// label1 // label1
// //
this.label1.AutoSize = true; this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9); this.label1.Location = new System.Drawing.Point(12, 13);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(59, 15); this.label1.Size = new System.Drawing.Size(59, 15);
this.label1.TabIndex = 4; this.label1.TabIndex = 4;
@ -90,6 +91,16 @@
this.label2.TabIndex = 5; this.label2.TabIndex = 5;
this.label2.Text = "Creation"; this.label2.Text = "Creation";
// //
// btnRefresh
//
this.btnRefresh.Location = new System.Drawing.Point(134, 5);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(58, 23);
this.btnRefresh.TabIndex = 1;
this.btnRefresh.Text = "Refresh";
this.btnRefresh.UseVisualStyleBackColor = true;
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
//
// RoomListForm // RoomListForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@ -99,6 +110,7 @@
this.Controls.Add(this.label1); this.Controls.Add(this.label1);
this.Controls.Add(this.btnCreate); this.Controls.Add(this.btnCreate);
this.Controls.Add(this.tbxRoomName); this.Controls.Add(this.tbxRoomName);
this.Controls.Add(this.btnRefresh);
this.Controls.Add(this.btnEnter); this.Controls.Add(this.btnEnter);
this.Controls.Add(this.lbxRoom); this.Controls.Add(this.lbxRoom);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
@ -108,6 +120,7 @@
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Room list"; this.Text = "Room list";
this.Activated += new System.EventHandler(this.RoomListForm_Activated); this.Activated += new System.EventHandler(this.RoomListForm_Activated);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.RoomListForm_FormClosing);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -121,5 +134,6 @@
private Button btnCreate; private Button btnCreate;
private Label label1; private Label label1;
private Label label2; private Label label2;
private Button btnRefresh;
} }
} }

@ -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;
@ -12,9 +14,18 @@ namespace Client
{ {
public partial class RoomListForm : Form public partial class RoomListForm : Form
{ {
private delegate void InvokedMethod();
public RoomListForm() public RoomListForm()
{ {
InitializeComponent(); InitializeComponent();
InitInstance();
}
private void InitInstance()
{
Singleton.Instance.CreateRoomResponsed += CreateRoomResponsed;
Singleton.Instance.RoomListResponsed += Instance_RoomListResponsed;
} }
private void btnEnter_Click(object sender, EventArgs e) private void btnEnter_Click(object sender, EventArgs e)
@ -25,12 +36,17 @@ namespace Client
return; return;
} }
ChatRoomForm chatRoomForm = new ChatRoomForm(); IAsyncResult ar = null;
chatRoomForm.Text = lbxRoom.SelectedItem.ToString(); ar = BeginInvoke(() =>
chatRoomForm.ShowDialog(); {
ChatRoomForm chatRoomForm = new ChatRoomForm();
chatRoomForm.Text = lbxRoom.SelectedItem.ToString();
chatRoomForm.ShowDialog();
EndInvoke(ar);
});
} }
private void btnCreate_Click(object sender, EventArgs e) private async void btnCreate_Click(object sender, EventArgs e)
{ {
string roomName = tbxRoomName.Text; string roomName = tbxRoomName.Text;
if (string.IsNullOrEmpty(roomName)) if (string.IsNullOrEmpty(roomName))
@ -39,14 +55,83 @@ namespace Client
return; return;
} }
ChatRoomForm chatRoomForm = new ChatRoomForm(); CreateRoomRequestPacket packet = new CreateRoomRequestPacket(roomName);
chatRoomForm.Text = roomName; await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None);
chatRoomForm.ShowDialog();
} }
private void RoomListForm_Activated(object sender, EventArgs e) private void RoomListForm_Activated(object sender, EventArgs e)
{
btnRefresh_Click(sender, e);
}
private void InvokeMethod(InvokedMethod method)
{
if (InvokeRequired)
{
lbxRoom.Invoke(new MethodInvoker(() =>
{
method();
}));
}
else
{
method();
}
}
private void CreateRoomResponsed(object? sender, EventArgs e)
{
if (sender == null)
return;
CreateRoomResponsePacket packet = (CreateRoomResponsePacket)sender;
if (packet.Code == StatusCode.Success)
{
string roomName = tbxRoomName.Text;
InvokeMethod(() =>
{
lbxRoom.Items.Add(roomName);
tbxRoomName.Text = "";
});
IAsyncResult ar = null;
ar = BeginInvoke(() =>
{
ChatRoomForm chatRoomForm = new ChatRoomForm();
chatRoomForm.Text = roomName;
chatRoomForm.ShowDialog();
EndInvoke(ar);
});
}
}
private void Instance_RoomListResponsed(object? sender, EventArgs e)
{
if (sender == null)
return;
RoomListResponsePacket packet = (RoomListResponsePacket)sender;
InvokeMethod(() =>
{
foreach (string item in packet.RoomNames)
{
lbxRoom.Items.Add(item);
}
});
}
private async void btnRefresh_Click(object sender, EventArgs e)
{ {
lbxRoom.Items.Clear(); lbxRoom.Items.Clear();
RoomListRequestPacket packet = new RoomListRequestPacket();
await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None);
}
private void RoomListForm_FormClosing(object sender, FormClosingEventArgs e)
{
Singleton.Instance.CreateRoomResponsed -= CreateRoomResponsed;
Singleton.Instance.RoomListResponsed -= Instance_RoomListResponsed;
Singleton.Instance.Socket.Shutdown(SocketShutdown.Send);
} }
} }
} }

@ -18,6 +18,8 @@ namespace Client
public Socket Socket { get; } = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); public Socket Socket { get; } = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public event EventHandler? LoginResponsed; public event EventHandler? LoginResponsed;
public event EventHandler? CreateRoomResponsed;
public event EventHandler? RoomListResponsed;
public async Task ConnectAsync(string ip, int port) public async Task ConnectAsync(string ip, int port)
{ {
@ -70,6 +72,16 @@ namespace Client
LoginResponsePacket packet = new LoginResponsePacket(dataBuffer); LoginResponsePacket packet = new LoginResponsePacket(dataBuffer);
LoginResponsed?.Invoke(packet, EventArgs.Empty); LoginResponsed?.Invoke(packet, EventArgs.Empty);
} }
else if (packetType == PacketType.CreateRoomResponse)
{
CreateRoomResponsePacket packet = new CreateRoomResponsePacket(dataBuffer);
CreateRoomResponsed?.Invoke(packet, EventArgs.Empty);
}
else if (packetType == PacketType.RoomListResponse)
{
RoomListResponsePacket packet = new RoomListResponsePacket(dataBuffer);
RoomListResponsed?.Invoke(packet, EventArgs.Empty);
}
} }
} }
} }

@ -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 CreateRoomRequestPacket : IPacket
{
public string RoomName { get; private set; }
public CreateRoomRequestPacket(string roomName)
{
RoomName = roomName;
}
public CreateRoomRequestPacket(byte[] buffer)
{
int cursor = 2;
short roomNameSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor));
cursor += sizeof(short);
RoomName = Encoding.UTF8.GetString(buffer, cursor, roomNameSize);
}
public byte[] Serialize()
{
// 2bytes header
// data: 2bytes packetType + 2bytes id size + id + 2bytes nickname size + nickname
byte[] packetType = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)PacketType.CreateRoomRequest));
byte[] roomName = Encoding.UTF8.GetBytes(RoomName);
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,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class CreateRoomResponsePacket : IPacket
{
public StatusCode Code { get; set; }
public CreateRoomResponsePacket(StatusCode code)
{
Code = code;
}
public CreateRoomResponsePacket(byte[] buffer)
{
Code = (StatusCode)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 2));
}
public byte[] Serialize()
{
// 2bytes header
// data: 2bytes packetType + code
byte[] packetType = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)PacketType.CreateRoomResponse));
byte[] code = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((int)Code));
short dataSize = (short)(packetType.Length + code.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(code, 0, buffer, cursor, code.Length);
return buffer;
}
}
}

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -12,6 +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 PServer(string ip, int port, int backlog) public PServer(string ip, int port, int backlog)
{ {
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port); IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
@ -37,13 +40,17 @@ namespace Core
Socket clientSocket = (Socket)sender; Socket clientSocket = (Socket)sender;
byte[] headerBuffer = new byte[2]; byte[] headerBuffer = new byte[2];
string id = "";
string nickname = "";
string roomName = "";
while (true) while (true)
{ {
// header buffer // header buffer
int n1 = await clientSocket.ReceiveAsync(headerBuffer, SocketFlags.None); int n1 = await clientSocket.ReceiveAsync(headerBuffer, SocketFlags.None);
if (n1 < 1) if (n1 < 1)
{ {
Console.WriteLine($"[{DateTime.Now}] Disconnect client: {clientSocket.RemoteEndPoint}"); Console.WriteLine($"[{DateTime.Now}] Disconnect client - {clientSocket.RemoteEndPoint}");
clientSocket.Dispose(); clientSocket.Dispose();
return; return;
} }
@ -67,11 +74,40 @@ namespace Core
if (packetType == PacketType.LoginRequest) if (packetType == PacketType.LoginRequest)
{ {
LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer); LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer);
Console.WriteLine($"Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}"); 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(StatusCode.Success);
await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None); await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None);
} }
else if (packetType == PacketType.CreateRoomRequest)
{
CreateRoomRequestPacket requestPacket = new CreateRoomRequestPacket(dataBuffer);
Room room = new Room();
if (Rooms.TryAdd(requestPacket.RoomName, room))
{
roomName = requestPacket.RoomName;
room.Users.TryAdd(id, nickname);
Console.WriteLine($"[{DateTime.Now}] CreateRoomRequest - RoomName: {roomName}");
CreateRoomResponsePacket responsePacket = new CreateRoomResponsePacket(StatusCode.Success);
await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None);
}
else
{
Console.WriteLine($"[{DateTime.Now}] CreateRoomRequest failed - RoomName: {requestPacket.RoomName}");
CreateRoomResponsePacket responsePacket = new CreateRoomResponsePacket(StatusCode.Failed);
await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None);
}
}
else if (packetType == PacketType.RoomListRequest)
{
RoomListResponsePacket packet = new RoomListResponsePacket(Rooms.Keys);
await clientSocket.SendAsync(packet.Serialize(), SocketFlags.None);
}
} }
} }
} }

@ -10,5 +10,9 @@ namespace Core
{ {
LoginRequest, LoginRequest,
LoginResponse, LoginResponse,
CreateRoomRequest,
CreateRoomResponse,
RoomListRequest,
RoomListResponse,
} }
} }

@ -0,0 +1,14 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class Room
{
public ConcurrentDictionary<string, string> Users { get; } = new ConcurrentDictionary<string, string>();
}
}

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class RoomListRequestPacket : IPacket
{
public byte[] Serialize()
{
byte[] packetType = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)PacketType.RoomListRequest));
short dataSize = (short)(packetType.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);
return buffer;
}
}
}

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public class RoomListResponsePacket : IPacket
{
public List<string> RoomNames { get; }
public RoomListResponsePacket(ICollection<string> roomNames)
{
RoomNames = new List<string>(roomNames);
}
public RoomListResponsePacket(byte[] buffer)
{
RoomNames = new List<string>();
for (int cursor = 2; cursor < buffer.Length;)
{
short roomNameSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor));
cursor += sizeof(short);
RoomNames.Add(Encoding.UTF8.GetString(buffer, cursor, roomNameSize));
cursor += roomNameSize;
}
}
public byte[] Serialize()
{
byte[] packetType = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)PacketType.RoomListResponse));
short dataSize = (short)(packetType.Length);
List<byte[]> temp = new List<byte[]>();
foreach (string item in RoomNames)
{
byte[] nameBuffer = Encoding.UTF8.GetBytes(item);
byte[] nameSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)nameBuffer.Length));
dataSize += (short)(nameBuffer.Length + nameSize.Length);
temp.Add(nameSize);
temp.Add(nameBuffer);
}
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;
foreach (byte[] item in temp)
{
Array.Copy(item, 0, buffer, cursor, item.Length);
cursor += item.Length;
}
return buffer;
}
}
}

@ -9,5 +9,6 @@ namespace Core
public enum StatusCode public enum StatusCode
{ {
Success = 200, Success = 200,
Failed = 500,
} }
} }

Loading…
Cancel
Save