syneffort 2 years ago
parent a635ecbdce
commit 3230581fb5
  1. 4
      Chat/Client/Client.csproj
  2. 2
      Chat/Client/LoginForm.Designer.cs
  3. 45
      Chat/Client/LoginForm.cs
  4. 62
      Chat/Client/Singleton.cs
  5. 13
      Chat/Core/IPacket.cs
  6. 74
      Chat/Core/LoginRequestPacket.cs
  7. 49
      Chat/Core/LoginResponsePacket.cs
  8. 11
      Chat/Core/PServer.cs
  9. 14
      Chat/Core/PacketType.cs
  10. 13
      Chat/Core/StatusCode.cs

@ -8,4 +8,8 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>
</Project> </Project>

@ -49,7 +49,7 @@
this.tbxId.Location = new System.Drawing.Point(79, 12); this.tbxId.Location = new System.Drawing.Point(79, 12);
this.tbxId.Name = "tbxId"; this.tbxId.Name = "tbxId";
this.tbxId.Size = new System.Drawing.Size(181, 23); this.tbxId.Size = new System.Drawing.Size(181, 23);
this.tbxId.TabIndex = 1; this.tbxId.TabIndex = 0;
// //
// label2 // label2
// //

@ -1,3 +1,6 @@
using Core;
using System.Net.Sockets;
namespace Client namespace Client
{ {
public partial class LoginForm : Form public partial class LoginForm : Form
@ -5,21 +8,55 @@ namespace Client
public LoginForm() public LoginForm()
{ {
InitializeComponent(); InitializeComponent();
InitInstance();
} }
private void btnLogin_Click(object sender, EventArgs e) private void InitInstance()
{ {
if (string.IsNullOrEmpty(tbxId.Text) || string.IsNullOrEmpty(tbxNickname.Text)) Singleton.Instance.LoginResponsed += LoginResponsed;
FormClosing += LoginForm_FormClosing;
}
private void LoginForm_FormClosing(object? sender, FormClosingEventArgs e)
{
Singleton.Instance.LoginResponsed -= LoginResponsed;
}
private async void btnLogin_Click(object sender, EventArgs e)
{
string id = tbxId.Text;
string nickname = tbxNickname.Text;
if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(nickname))
{ {
MessageBox.Show("Please input ID and Nickname."); MessageBox.Show("Please input ID and Nickname.");
return; return;
} }
Singleton.Instance.Id = tbxId.Text; await Singleton.Instance.ConnectAsync("127.0.0.1", 20000);
Singleton.Instance.Nickname = tbxNickname.Text;
Singleton.Instance.Id = id;
Singleton.Instance.Nickname = nickname;
LoginRequestPacket packet = new LoginRequestPacket(id, nickname);
await Singleton.Instance.SendAsync(packet.Serialize(), SocketFlags.None);
}
private void LoginResponsed(object? sender, EventArgs e)
{
if (sender == null)
return;
LoginResponsePacket packet = (LoginResponsePacket)sender;
MessageBox.Show(packet.Code.ToString());
if (packet.Code != StatusCode.Success)
{
RoomListForm roomListForm = new RoomListForm(); RoomListForm roomListForm = new RoomListForm();
roomListForm.ShowDialog(); roomListForm.ShowDialog();
} }
else
{
Singleton.Instance.Socket.Shutdown(SocketShutdown.Send);
}
}
} }
} }

@ -1,6 +1,9 @@
using System; using Core;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,5 +15,62 @@ namespace Client
public string Id { get; set; } = ""; public string Id { get; set; } = "";
public string Nickname { get; set; } = ""; public string Nickname { get; set; } = "";
public Socket Socket { get; } = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public event EventHandler? LoginResponsed;
public async Task ConnectAsync(string ip, int port)
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
await this.Socket.ConnectAsync(endPoint);
ThreadPool.QueueUserWorkItem(ReceiveAsync, this.Socket);
}
public async Task<int> SendAsync(byte[] buffer, SocketFlags socketFlags)
{
return await this.Socket.SendAsync(buffer, socketFlags);
}
private async void ReceiveAsync(object? sender)
{
if (sender == null)
return;
Socket socket = (Socket)sender;
byte[] headerBuffer = new byte[2];
while (true)
{
// header buffer
int n1 = await socket.ReceiveAsync(headerBuffer, SocketFlags.None);
if (n1 < 1)
{
Console.WriteLine($"[{DateTime.Now}] Disconnect server: {socket.RemoteEndPoint}");
socket.Dispose();
return;
}
else if (n1 == 1)
{
await socket.ReceiveAsync(new ArraySegment<byte>(headerBuffer, 1, 1), SocketFlags.None);
}
// data buffer
short dataSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(headerBuffer));
byte[] dataBuffer = new byte[dataSize];
int totalRecv = 0;
while (totalRecv < dataSize)
{
int n2 = await socket.ReceiveAsync(new ArraySegment<byte>(dataBuffer, totalRecv, dataSize - totalRecv), SocketFlags.None);
totalRecv += n2;
}
PacketType packetType = (PacketType)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(dataBuffer));
if (packetType == PacketType.LoginResponse)
{
LoginResponsePacket packet = new LoginResponsePacket(dataBuffer);
LoginResponsed?.Invoke(packet, EventArgs.Empty);
}
}
}
} }
} }

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
internal interface IPacket
{
byte[] Serialize();
}
}

@ -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 LoginRequestPacket : IPacket
{
public string Id { get; private set; }
public string NickName { get; private set; }
public LoginRequestPacket(string id, string nickname)
{
Id = id;
NickName = nickname;
}
public LoginRequestPacket(byte[] buffer)
{
int cursor = 2;
short idSize = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, cursor));
cursor += sizeof(short);
Id = Encoding.UTF8.GetString(buffer, cursor, idSize);
cursor += idSize;
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.LoginRequest));
byte[] id = Encoding.UTF8.GetBytes(Id);
byte[] idSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)id.Length));
byte[] nickname = Encoding.UTF8.GetBytes(NickName);
byte[] nicknameSize = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)nickname.Length));
short dataSize = (short)(packetType.Length + id.Length + idSize.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(idSize, 0, buffer, cursor, idSize.Length);
cursor += idSize.Length;
Array.Copy(id, 0, buffer, cursor, id.Length);
cursor += id.Length;
Array.Copy(nicknameSize, 0, buffer, cursor, nicknameSize.Length);
cursor += nicknameSize.Length;
Array.Copy(nickname, 0, buffer, cursor, nickname.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 LoginResponsePacket : IPacket
{
public StatusCode Code { get; set; }
public LoginResponsePacket(StatusCode code)
{
Code = code;
}
public LoginResponsePacket(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.LoginResponse));
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;
}
}
}

@ -62,7 +62,16 @@ namespace Core
int n2 = await clientSocket.ReceiveAsync(new ArraySegment<byte>(dataBuffer, totalRecv, dataSize - totalRecv), SocketFlags.None); int n2 = await clientSocket.ReceiveAsync(new ArraySegment<byte>(dataBuffer, totalRecv, dataSize - totalRecv), SocketFlags.None);
totalRecv += n2; totalRecv += n2;
} }
Console.WriteLine($"[{DateTime.Now}] {clientSocket.RemoteEndPoint} client: {Encoding.UTF8.GetString(dataBuffer)}");
PacketType packetType = (PacketType)IPAddress.NetworkToHostOrder(BitConverter.ToInt16(dataBuffer));
if (packetType == PacketType.LoginRequest)
{
LoginRequestPacket requestPacket = new LoginRequestPacket(dataBuffer);
Console.WriteLine($"Id: {requestPacket.Id}, Nickname: {requestPacket.NickName}");
LoginResponsePacket responsePacket = new LoginResponsePacket(StatusCode.Success);
await clientSocket.SendAsync(responsePacket.Serialize(), SocketFlags.None);
}
} }
} }
} }

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public enum PacketType
{
LoginRequest,
LoginResponse,
}
}

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core
{
public enum StatusCode
{
Success = 200,
}
}
Loading…
Cancel
Save