feat: wip: use TcpClient
This commit is contained in:
parent
a7344f5a7b
commit
35755eb7ec
9 changed files with 138 additions and 32 deletions
|
@ -32,7 +32,7 @@ internal class Program
|
|||
{
|
||||
byte[] bytes = udpClient.Receive(ref serverEP);
|
||||
|
||||
MessageMemoryStream stream = new(bytes);
|
||||
MessageNetworkStream stream = new(bytes);
|
||||
|
||||
ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
|
||||
switch (packetIn)
|
||||
|
|
|
@ -4,10 +4,6 @@ namespace GServer.Common;
|
|||
|
||||
public class MessageMemoryStream : MemoryStream
|
||||
{
|
||||
public MessageMemoryStream()
|
||||
{
|
||||
}
|
||||
|
||||
public MessageMemoryStream(byte[] buffer) : base(buffer)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class AuthResponseMessage : BaseMessage, IMessage<AuthResponseMessage>
|
|||
FailureReason = failureReason;
|
||||
}
|
||||
|
||||
public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE)
|
||||
public AuthResponseMessage(MessageNetworkStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE)
|
||||
{
|
||||
IsSuccessful = stream.ReadBoolean();
|
||||
|
||||
|
@ -47,7 +47,7 @@ public class AuthResponseMessage : BaseMessage, IMessage<AuthResponseMessage>
|
|||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using MessageMemoryStream stream = new();
|
||||
using MessageNetworkStream stream = new();
|
||||
|
||||
stream.WriteByte(PacketId);
|
||||
stream.WriteBoolean(IsSuccessful);
|
||||
|
|
|
@ -12,7 +12,7 @@ public class ListServersResponseMessage : BaseMessage, IMessage<ListServersRespo
|
|||
ServerListings = serverListings;
|
||||
}
|
||||
|
||||
public ListServersResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.LIST_SERVERS_RESPONSE)
|
||||
public ListServersResponseMessage(MessageNetworkStream stream) : base((byte)ClientPacketIn.LIST_SERVERS_RESPONSE)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public class AuthMessage : BaseMessage, IMessage<AuthMessage>
|
|||
Password = password;
|
||||
}
|
||||
|
||||
public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.AUTH)
|
||||
public AuthMessage(MessageNetworkStream stream) : base((byte)ServerPacketIn.AUTH)
|
||||
{
|
||||
byte usernameLen = (byte)stream.ReadByte();
|
||||
string username = stream.ReadUTF8String(usernameLen);
|
||||
|
|
6
GServer.Server/GameServerOptions.cs
Normal file
6
GServer.Server/GameServerOptions.cs
Normal file
|
@ -0,0 +1,6 @@
|
|||
namespace GServer.Server;
|
||||
|
||||
public class GameServerOptions
|
||||
{
|
||||
public int PacketLength { get; set; }
|
||||
}
|
116
GServer.Server/TCPGameServer.cs
Normal file
116
GServer.Server/TCPGameServer.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using GServer.Common;
|
||||
using GServer.Common.Networking.Enums;
|
||||
using GServer.Common.Networking.Messages.Client;
|
||||
using GServer.Common.Networking.Messages.Server;
|
||||
|
||||
namespace GServer.Server;
|
||||
|
||||
public class TCPGameServer : IDisposable
|
||||
{
|
||||
private readonly TcpListener _tcpListener;
|
||||
private readonly IPEndPoint _endPoint;
|
||||
private readonly GameServerOptions _options;
|
||||
|
||||
public TCPGameServer(IPEndPoint endPoint, GameServerOptions options)
|
||||
{
|
||||
_endPoint = endPoint;
|
||||
_options = options;
|
||||
|
||||
_tcpListener = new TcpListener(endPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bind the server to the given endpoint.
|
||||
/// </summary>
|
||||
public async void Start()
|
||||
{
|
||||
Console.WriteLine("Starting TCPGameServer listener...");
|
||||
_tcpListener.Start();
|
||||
Console.WriteLine($"TCPGameServer listening on {_endPoint}");
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await ProcessAsync(await _tcpListener.AcceptTcpClientAsync());
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_tcpListener.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin processing messages
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task ProcessAsync(TcpClient tcpClient)
|
||||
{
|
||||
try
|
||||
{
|
||||
using NetworkStream stream = tcpClient.GetStream();
|
||||
|
||||
byte[] data = new byte[_options.PacketLength];
|
||||
int bytesRead = 0;
|
||||
int chunkSize = 1;
|
||||
|
||||
// Read everything into the data buffer
|
||||
while (bytesRead < data.Length && chunkSize > 0)
|
||||
{
|
||||
bytesRead +=
|
||||
chunkSize =
|
||||
await stream.ReadAsync(data.AsMemory(bytesRead, data.Length - bytesRead));
|
||||
}
|
||||
|
||||
// Use the in-memory buffer to process the message
|
||||
await HandleMessageAsync(stream.Socket, new MessageMemoryStream(data));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream)
|
||||
{
|
||||
ServerPacketIn serverPacketIn = (ServerPacketIn)messageStream.ReadByte();
|
||||
|
||||
Console.WriteLine($"Handling message {serverPacketIn} from {client}...");
|
||||
|
||||
switch (serverPacketIn)
|
||||
{
|
||||
case ServerPacketIn.AUTH:
|
||||
AuthMessage msg = new(messageStream);
|
||||
|
||||
AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123"
|
||||
? new(true, Guid.NewGuid().ToString(), null)
|
||||
: new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
|
||||
|
||||
byte[] buffer = resp.Serialize();
|
||||
_ = await TcpClient.Client.SendAsync(buffer,
|
||||
|
||||
break;
|
||||
|
||||
case ServerPacketIn.LIST_SERVERS:
|
||||
throw new NotImplementedException();
|
||||
|
||||
default:
|
||||
Console.WriteLine($"Received unsupported packet.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
TcpClient.Close();
|
||||
TcpClient.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@ using System.Net;
|
|||
using System.Net.Sockets;
|
||||
using GServer.Common;
|
||||
using GServer.Common.Networking.Enums;
|
||||
using GServer.Common.Networking.Messages.Client;
|
||||
using GServer.Common.Networking.Messages.Server;
|
||||
|
||||
namespace GServer.Server;
|
||||
|
||||
|
@ -43,7 +41,7 @@ public class UDPGameServer : IDisposable
|
|||
{
|
||||
UdpReceiveResult res = await UdpClient.ReceiveAsync();
|
||||
byte[] bytes = res.Buffer;
|
||||
MessageMemoryStream stream = new(bytes);
|
||||
MessageNetworkStream stream = new(bytes);
|
||||
await HandleMessageAsync(stream, res.RemoteEndPoint);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -52,32 +50,17 @@ public class UDPGameServer : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private async Task HandleMessageAsync(MessageMemoryStream stream, IPEndPoint remoteEndPoint)
|
||||
private async Task HandleMessageAsync(MessageNetworkStream stream, IPEndPoint remoteEndPoint)
|
||||
{
|
||||
ServerPacketIn serverPacketIn = (ServerPacketIn)stream.ReadByte();
|
||||
byte serverPacketInByte = (byte)stream.ReadByte();
|
||||
ServerPacketIn serverPacketIn = (ServerPacketIn)serverPacketInByte;
|
||||
|
||||
Console.WriteLine($"Handling message {serverPacketIn} from {remoteEndPoint}...");
|
||||
Console.WriteLine($"Handling UDP message {serverPacketInByte} from {remoteEndPoint}...");
|
||||
|
||||
switch (serverPacketIn)
|
||||
{
|
||||
case ServerPacketIn.AUTH:
|
||||
AuthMessage msg = new(stream);
|
||||
|
||||
AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123"
|
||||
? new(true, Guid.NewGuid().ToString(), null)
|
||||
: new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
|
||||
|
||||
byte[] buffer = resp.Serialize();
|
||||
_ = await UdpClient.SendAsync(buffer, buffer.Length, remoteEndPoint);
|
||||
|
||||
break;
|
||||
|
||||
case ServerPacketIn.LIST_SERVERS:
|
||||
throw new NotImplementedException();
|
||||
|
||||
default:
|
||||
Console.WriteLine($"Received unsupported packet.");
|
||||
break;
|
||||
throw new NotImplementedException($"Received unsupported packet {serverPacketInByte}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
notes
Normal file
5
notes
Normal file
|
@ -0,0 +1,5 @@
|
|||
potentially move flag type to short from byte
|
||||
|
||||
|
||||
single thread accept
|
||||
- spin up multiple threads to deal with actions
|
Loading…
Add table
Reference in a new issue