This commit is contained in:
Aaron Yarborough 2024-09-11 21:38:32 +01:00
parent c640988354
commit 6d80785dfd
26 changed files with 389 additions and 371 deletions

View file

@ -1,73 +1,73 @@
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using GServer.Common; using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums; using GServer.Common.Networking.Enums;
using GServer.Common.Networking.Messages.Client; using GServer.Common.Networking.Messages.Client;
using GServer.Common.Networking.Messages.Server; using GServer.Common.Networking.Messages.Server;
internal class Program namespace GServer.Client;
{
private const int SERVER_PORT = 11000; public class Program
{
private static void Main(string[] args) private const int ServerPort = 11000;
{
IPEndPoint serverEP = new(IPAddress.Any, SERVER_PORT); private static void Main(string[] args)
{
TcpClient tcpClient = new(); IPEndPoint serverEp = new(IPAddress.Any, ServerPort);
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
tcpClient.Connect(serverEP); TcpClient tcpClient = new();
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
Console.WriteLine("Username..."); tcpClient.Connect(serverEp);
string username = Console.ReadLine()!;
Console.WriteLine("Username...");
Console.WriteLine("Password..."); string username = Console.ReadLine()!;
string password = Console.ReadLine()!;
Console.WriteLine("Password...");
AuthMessage authMessage = new(username, password); string password = Console.ReadLine()!;
_ = tcpClient.Client.Send(authMessage.Serialize());
AuthMessage authMessage = new(username, password);
try _ = tcpClient.Client.Send(authMessage.Serialize());
{
while (true) try
{ {
byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize]; while (true)
_ = tcpClient.Client.Receive(bytes); {
byte[] bytes = new byte[tcpClient.Client.ReceiveBufferSize];
MessageMemoryStream stream = new(bytes); _ = tcpClient.Client.Receive(bytes);
ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte(); MessageMemoryStream stream = new(bytes);
switch (packetIn)
{ ClientPacketIn packetIn = (ClientPacketIn)stream.ReadByte();
case ClientPacketIn.AUTH_RESPONSE: switch (packetIn)
AuthResponseMessage authResultMessage = new(stream); {
case ClientPacketIn.AuthResponse:
Console.WriteLine("Success = " + authResultMessage.IsSuccessful); AuthResponseMessage authResultMessage = new(stream);
Console.WriteLine("SessionToken = " + authResultMessage.SessionToken ?? "null");
Console.WriteLine("FailureReason = " + authResultMessage.FailureReason ?? "null"); Console.WriteLine("Success = " + authResultMessage.IsSuccessful);
Console.WriteLine("SessionToken = " + authResultMessage.SessionToken);
break; Console.WriteLine("FailureReason = " + authResultMessage.FailureReason);
case ClientPacketIn.LIST_SERVERS_RESPONSE: break;
break;
case ClientPacketIn.ListServersResponse:
case ClientPacketIn.UNKNOWN: break;
break;
case ClientPacketIn.Unknown:
default: break;
Console.WriteLine($"Received unsupported packet.");
break; default:
} Console.WriteLine("Received unsupported packet.");
} break;
} }
catch (Exception ex) }
{ }
Console.WriteLine(ex); catch (Exception ex)
} {
finally Console.WriteLine(ex);
{ }
tcpClient.Close(); finally
} {
tcpClient.Close();
}
} }
} }

View file

@ -1,11 +1,11 @@
using System.Text; using System.Text;
namespace GServer.Common; namespace GServer.Common.Extensions;
public static class StringExtensions public static class StringExtensions
{ {
public static byte[] GetASCIIBytes(this string value) public static byte[] GetAsciiBytes(this string value)
{ {
return Encoding.ASCII.GetBytes(value); return Encoding.ASCII.GetBytes(value);
} }
} }

View file

@ -5,7 +5,7 @@ public record ServerListing
public required string Name { get; set; } public required string Name { get; set; }
public required string Description { get; set; } public required string Description { get; set; }
public ushort Playercount { get; set; } public ushort Playercount { get; set; }
public required string IPAddress { get; set; } public required string IpAddress { get; set; }
public ushort Port { get; set; } public ushort Port { get; set; }
public ServerTier ServerTier { get; set; } public ServerTier ServerTier { get; set; }
} }

View file

@ -1,6 +1,6 @@
using System.Text; using System.Text;
namespace GServer.Common; namespace GServer.Common.Networking.Core;
public class MessageMemoryStream : MemoryStream public class MessageMemoryStream : MemoryStream
{ {
@ -31,7 +31,7 @@ public class MessageMemoryStream : MemoryStream
return BitConverter.ToInt16(buffer); return BitConverter.ToInt16(buffer);
} }
public string ReadUTF8String(int length) public string ReadUtf8String(int length)
{ {
byte[] bytes = new byte[length]; byte[] bytes = new byte[length];
_ = Read(bytes, 0, length); _ = Read(bytes, 0, length);
@ -49,7 +49,7 @@ public class MessageMemoryStream : MemoryStream
Write(bytes, 0, 2); Write(bytes, 0, 2);
} }
public void WriteUTF8String(string value) public void WriteUtf8String(string value)
{ {
byte[] bytes = Encoding.UTF8.GetBytes(value); byte[] bytes = Encoding.UTF8.GetBytes(value);
Write(bytes, 0, bytes.Length); Write(bytes, 0, bytes.Length);

View file

@ -5,12 +5,12 @@ public enum ClientPacketIn : byte
/// <summary> /// <summary>
/// Represents an auth result from the server. /// Represents an auth result from the server.
/// </summary> /// </summary>
AUTH_RESPONSE = 1, AuthResponse = 1,
/// <summary> /// <summary>
/// Contains a list of server listings. /// Contains a list of server listings.
/// </summary> /// </summary>
LIST_SERVERS_RESPONSE = 2, ListServersResponse = 2,
UNKNOWN = 255 Unknown = 255
} }

View file

@ -2,6 +2,6 @@ namespace GServer.Common.Networking.Enums;
public enum ServerPacketIn : byte public enum ServerPacketIn : byte
{ {
AUTH = 1, Auth = 1,
LIST_SERVERS = 2 ListServers = 2
} }

View file

@ -4,7 +4,7 @@ public abstract class BaseMessage
{ {
protected readonly byte PacketId; protected readonly byte PacketId;
public BaseMessage(byte packetId) protected BaseMessage(byte packetId)
{ {
PacketId = packetId; PacketId = packetId;
} }

View file

@ -1,68 +1,69 @@
using System.Text; using System.Text;
using GServer.Common.Networking.Enums; using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums;
namespace GServer.Common.Networking.Messages.Client;
namespace GServer.Common.Networking.Messages.Client;
public enum AuthResponseFailure : byte
{ public enum AuthResponseFailure : byte
IncorrectLoginOrPassword, {
Unknown IncorrectLoginOrPassword,
} Unknown
}
public class AuthResponseMessage : BaseMessage, IMessage<AuthResponseMessage>
{ public class AuthResponseMessage : BaseMessage, IMessage<AuthResponseMessage>
public bool IsSuccessful { get; private set; } {
public bool IsSuccessful { get; }
/// <summary>
/// Used to authenticate the user. Only set if IsSuccessful is true. /// <summary>
/// </summary> /// Used to authenticate the user. Only set if IsSuccessful is true.
public string? SessionToken { get; private set; } /// </summary>
public string? SessionToken { get; }
/// <summary>
/// Reason for auth failure. Only set is IsSuccessful is false. /// <summary>
/// </summary> /// Reason for auth failure. Only set is IsSuccessful is false.
public AuthResponseFailure? FailureReason { get; private set; } /// </summary>
public AuthResponseFailure? FailureReason { get; }
public AuthResponseMessage(bool isSuccessful, string? sessionToken = null, AuthResponseFailure? failureReason = null) : base((byte)ClientPacketIn.AUTH_RESPONSE)
{ public AuthResponseMessage(bool isSuccessful, string? sessionToken = null, AuthResponseFailure? failureReason = null) : base((byte)ClientPacketIn.AuthResponse)
IsSuccessful = isSuccessful; {
SessionToken = sessionToken; IsSuccessful = isSuccessful;
FailureReason = failureReason; SessionToken = sessionToken;
} FailureReason = failureReason;
}
public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AUTH_RESPONSE)
{ public AuthResponseMessage(MessageMemoryStream stream) : base((byte)ClientPacketIn.AuthResponse)
IsSuccessful = stream.ReadBoolean(); {
IsSuccessful = stream.ReadBoolean();
if (IsSuccessful)
{ if (IsSuccessful)
ushort sessionTokenLen = stream.ReadUInt16(); {
SessionToken = stream.ReadUTF8String(sessionTokenLen); ushort sessionTokenLen = stream.ReadUInt16();
} SessionToken = stream.ReadUtf8String(sessionTokenLen);
else }
{ else
FailureReason = (AuthResponseFailure)stream.ReadByte(); {
} FailureReason = (AuthResponseFailure)stream.ReadByte();
} }
}
public byte[] Serialize()
{ public byte[] Serialize()
using MessageMemoryStream stream = new(); {
using MessageMemoryStream stream = new();
stream.WriteByte(PacketId);
stream.WriteBoolean(IsSuccessful); stream.WriteByte(PacketId);
stream.WriteBoolean(IsSuccessful);
if (IsSuccessful)
{ if (IsSuccessful)
short sessionTokenByteLen = (short)Encoding.UTF8.GetByteCount(SessionToken!); {
stream.WriteUInt16(sessionTokenByteLen); short sessionTokenByteLen = (short)Encoding.UTF8.GetByteCount(SessionToken!);
stream.WriteUTF8String(SessionToken!); stream.WriteUInt16(sessionTokenByteLen);
} stream.WriteUtf8String(SessionToken!);
else }
{ else
stream.WriteByte((byte)FailureReason!); {
} stream.WriteByte((byte)FailureReason!);
}
return stream.ToArray();
} return stream.ToArray();
} }
}

View file

@ -1,4 +1,5 @@
using System.Net.Sockets; using System.Net.Sockets;
using GServer.Common.Networking.Core;
namespace GServer.Common.Networking.Messages; namespace GServer.Common.Networking.Messages;

View file

@ -1,26 +1,27 @@
using System.Text; using System.Text;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums; using GServer.Common.Networking.Enums;
namespace GServer.Common.Networking.Messages.Server; namespace GServer.Common.Networking.Messages.Server;
public class AuthMessage : BaseMessage, IMessage<AuthMessage> public class AuthMessage : BaseMessage, IMessage<AuthMessage>
{ {
public string Username { get; private set; } public string Username { get; }
public string Password { get; private set; } public string Password { get; }
public AuthMessage(string username, string password) : base((byte)ServerPacketIn.AUTH) public AuthMessage(string username, string password) : base((byte)ServerPacketIn.Auth)
{ {
Username = username; Username = username;
Password = password; Password = password;
} }
public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.AUTH) public AuthMessage(MessageMemoryStream stream) : base((byte)ServerPacketIn.Auth)
{ {
byte usernameLen = (byte)stream.ReadByte(); byte usernameLen = (byte)stream.ReadByte();
string username = stream.ReadUTF8String(usernameLen); string username = stream.ReadUtf8String(usernameLen);
byte passwordLen = (byte)stream.ReadByte(); byte passwordLen = (byte)stream.ReadByte();
string password = stream.ReadUTF8String(passwordLen); string password = stream.ReadUtf8String(passwordLen);
Username = username; Username = username;
Password = password; Password = password;

View file

@ -4,7 +4,7 @@ namespace GServer.Common.Networking.Messages.Server;
public class ListServersMessage : BaseMessage, IMessage<ListServersMessage> public class ListServersMessage : BaseMessage, IMessage<ListServersMessage>
{ {
public ListServersMessage() : base((byte)ServerPacketIn.LIST_SERVERS) public ListServersMessage() : base((byte)ServerPacketIn.ListServers)
{ {
} }

View file

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NetCoreServer" Version="8.0.7" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,51 @@
using System.Net.Sockets;
using NetCoreServer;
namespace GServer.NCSServer;
public class GameSession : TcpSession
{
public GameSession(TcpServer server) : base(server)
{
}
protected override void OnConnected()
{
Console.WriteLine($"Chat TCP session with Id {Id} connected!");
}
protected override void OnConnecting()
{
base.OnConnecting();
}
protected override void OnDisconnecting()
{
base.OnDisconnecting();
}
protected override void OnDisconnected()
{
Console.WriteLine($"Chat TCP session with Id {Id} disconnected!");
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
base.OnReceived(buffer, offset, size);
}
protected override void OnSent(long sent, long pending)
{
base.OnSent(sent, pending);
}
protected override void OnEmpty()
{
base.OnEmpty();
}
protected override void OnError(SocketError error)
{
base.OnError(error);
}
}

View file

@ -0,0 +1,4 @@
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
WebApplication app = builder.Build();
app.Run();

View file

@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:58673",
"sslPort": 44396
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5051",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7192;http://localhost:5051",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View file

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GServer.Common\GServer.Common.csproj" /> <ProjectReference Include="..\GServer.Common\GServer.Common.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>

View file

@ -2,5 +2,4 @@
public class GameServerOptions public class GameServerOptions
{ {
public int PacketLength { get; set; }
} }

View file

@ -1,15 +1,23 @@
using System.Net; using System.Net;
using GServer.Server;
namespace GServer.Server;
// ReSharper disable once ClassNeverInstantiated.Global
internal sealed class Program internal sealed class Program
{ {
private const int LISTEN_PORT = 11000; private const int ListenPort = 11000;
private static void Main(string[] args) private static void Main(string[] args)
{ {
TCPGameServer server = new(new IPEndPoint(IPAddress.Any, LISTEN_PORT), new GameServerOptions());
CancellationTokenSource cancellationTokenSource = new(); CancellationTokenSource cancellationTokenSource = new();
server.Start(cancellationTokenSource.Token).Wait(); Thread serverWorker = new(delegate()
{
TcpGameServer server = new(new IPEndPoint(IPAddress.Any, ListenPort), new GameServerOptions());
server.Start();
});
serverWorker.Start();
} }
} }

View file

@ -1,24 +0,0 @@
using GServer.Common.Game.Entities;
namespace GServer.Server.Services;
public class ServerListService
{
public ServerListService()
{
}
public IEnumerable<ServerListing> List()
{
return [
new ServerListing
{
Name = "Smallville",
Description = "A tiny development server!",
IPAddress = "localhost",
Port = 11001,
Playercount = 1,
}
];
}
}

View file

@ -1,94 +0,0 @@
using System.Net;
using System.Net.Sockets;
using GServer.Common;
using GServer.Common.Networking.Messages;
namespace GServer.Server;
public class TCPGameServer : IDisposable
{
private readonly TcpListener _tcpListener;
private readonly IPEndPoint _endPoint;
private readonly GameServerOptions _options;
private readonly IMessageHandler _messageHandler;
public TCPGameServer(IPEndPoint endPoint, GameServerOptions options)
{
_endPoint = endPoint;
_options = options;
_tcpListener = new TcpListener(endPoint);
_messageHandler = new TCPMessageHandler();
}
/// <summary>
/// Bind the server to the given endpoint.
/// </summary>
public async Task Start(CancellationToken cancellationToken)
{
Console.WriteLine("Starting TCPGameServer listener...");
_tcpListener.Start();
_ = cancellationToken.Register(_tcpListener.Stop);
Console.WriteLine($"TCPGameServer listening on {_endPoint}");
while (!cancellationToken.IsCancellationRequested)
{
try
{
using TcpClient tcpClient = await _tcpListener.AcceptTcpClientAsync(cancellationToken);
await ProcessAsync(tcpClient);
}
catch (SocketException) when (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("TcpListener stopped listening because cancellation was requested.");
}
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[tcpClient.ReceiveBufferSize];
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 _messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}

View file

@ -0,0 +1,75 @@
using System.Net;
using System.Net.Sockets;
using GServer.Common.Networking.Core;
using GServer.Common.Networking.Messages;
namespace GServer.Server;
public class TcpGameServer(IPEndPoint endPoint, GameServerOptions options) : IDisposable
{
private readonly GameServerOptions _options = options;
private readonly TcpListener _tcpListener = new(endPoint);
private readonly IMessageHandler _messageHandler = new TcpMessageHandler();
/// <summary>
/// Bind the server to the given endpoint.
/// </summary>
public void Start()
{
Console.WriteLine($"Starting ${nameof(TcpGameServer)} listener...");
_tcpListener.Start();
Console.WriteLine($"{nameof(TcpGameServer)} listening on {endPoint}");
while (true)
{
try
{
Console.WriteLine("Waiting for a connection...");
_tcpListener.AcceptTcpClient();
Console.WriteLine("Client accepted!");
Thread worker = new Thread(new ParameterizedThreadStart(HandleClient!));
worker.Start();
}
finally
{
_tcpListener.Stop();
}
}
}
private void HandleClient(object clientObj)
{
TcpClient tcpClient = (TcpClient)clientObj;
try
{
using NetworkStream stream = tcpClient.GetStream();
byte[] data = new byte[tcpClient.ReceiveBufferSize];
while (stream.Read(data, 0, data.Length) != 0)
{
// Use the in-memory buffer to process the message
_messageHandler.HandleMessageAsync(stream.Socket, new MessageMemoryStream(data)).Wait();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private async void Stop()
{
Console.WriteLine($"Stopping ${nameof(TcpGameServer)} listener...");
_tcpListener.Stop();
Console.WriteLine($"Stopped ${nameof(TcpGameServer)} listener.");
}
public void Dispose()
{
Stop();
GC.SuppressFinalize(this);
}
}

View file

@ -1,5 +1,5 @@
using System.Net.Sockets; using System.Net.Sockets;
using GServer.Common; using GServer.Common.Networking.Core;
using GServer.Common.Networking.Enums; using GServer.Common.Networking.Enums;
using GServer.Common.Networking.Messages; using GServer.Common.Networking.Messages;
using GServer.Common.Networking.Messages.Client; using GServer.Common.Networking.Messages.Client;
@ -7,12 +7,8 @@ using GServer.Common.Networking.Messages.Server;
namespace GServer.Server; namespace GServer.Server;
public class TCPMessageHandler : IMessageHandler public class TcpMessageHandler : IMessageHandler
{ {
public TCPMessageHandler()
{
}
public async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream) public async Task HandleMessageAsync(Socket clientSocket, MessageMemoryStream messageStream)
{ {
ServerPacketIn serverPacketIn = (ServerPacketIn)messageStream.ReadByte(); ServerPacketIn serverPacketIn = (ServerPacketIn)messageStream.ReadByte();
@ -21,11 +17,11 @@ public class TCPMessageHandler : IMessageHandler
switch (serverPacketIn) switch (serverPacketIn)
{ {
case ServerPacketIn.AUTH: case ServerPacketIn.Auth:
AuthMessage msg = new(messageStream); AuthMessage msg = new(messageStream);
AuthResponseMessage resp = msg.Username == "aaronyarbz" && msg.Password == "password123" AuthResponseMessage resp = msg is { Username: "aaronyarbz", Password: "password123" }
? new(true, Guid.NewGuid().ToString(), null) ? new(true, Guid.NewGuid().ToString(), failureReason: null)
: new(false, null, AuthResponseFailure.IncorrectLoginOrPassword); : new(false, null, AuthResponseFailure.IncorrectLoginOrPassword);
byte[] buffer = resp.Serialize(); byte[] buffer = resp.Serialize();
@ -33,7 +29,7 @@ public class TCPMessageHandler : IMessageHandler
break; break;
case ServerPacketIn.LIST_SERVERS: case ServerPacketIn.ListServers:
throw new NotImplementedException(); throw new NotImplementedException();
default: default:

View file

@ -1,74 +0,0 @@
using System.Net;
using System.Net.Sockets;
using GServer.Common;
using GServer.Common.Networking.Enums;
namespace GServer.Server;
public class UDPGameServer : IDisposable
{
public readonly UdpClient UdpClient;
private readonly IPEndPoint _endPoint;
public UDPGameServer(IPEndPoint endPoint)
{
_endPoint = endPoint;
UdpClient = new UdpClient();
UdpClient.Client.SetSocketOption(
SocketOptionLevel.Socket,
SocketOptionName.ReuseAddress,
true);
}
/// <summary>
/// Bind the server to the given endpoint.
/// </summary>
public void Start()
{
UdpClient.Client.Bind(_endPoint);
Console.WriteLine($"UDPGameServer listening on {_endPoint}");
}
/// <summary>
/// Begin processing messages
/// </summary>
/// <returns></returns>
public async Task ProcessAsync()
{
try
{
UdpReceiveResult res = await UdpClient.ReceiveAsync();
byte[] bytes = res.Buffer;
MessageMemoryStream stream = new(bytes);
await HandleMessageAsync(stream, res.RemoteEndPoint);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
private async Task HandleMessageAsync(MessageMemoryStream stream, IPEndPoint remoteEndPoint)
{
byte serverPacketInByte = (byte)stream.ReadByte();
ServerPacketIn serverPacketIn = (ServerPacketIn)serverPacketInByte;
Console.WriteLine($"Handling UDP message {serverPacketInByte} from {remoteEndPoint}...");
throw serverPacketIn switch
{
ServerPacketIn.AUTH => new NotImplementedException(),
ServerPacketIn.LIST_SERVERS => new NotImplementedException(),
_ => new NotImplementedException($"Received unsupported packet {serverPacketInByte}"),
};
}
public void Dispose()
{
UdpClient.Close();
UdpClient.Dispose();
GC.SuppressFinalize(this);
}
}

View file

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.Server", "GServer.S
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.Client", "GServer.Client\GServer.Client.csproj", "{C105363D-E719-4296-94A2-01170E603889}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.Client", "GServer.Client\GServer.Client.csproj", "{C105363D-E719-4296-94A2-01170E603889}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GServer.NCSServer", "GServer.NCSServer\GServer.NCSServer.csproj", "{29CBF617-0334-4DC0-A61E-6F03796AF66F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{C105363D-E719-4296-94A2-01170E603889}.Debug|Any CPU.Build.0 = Debug|Any CPU {C105363D-E719-4296-94A2-01170E603889}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.ActiveCfg = Release|Any CPU {C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.Build.0 = Release|Any CPU {C105363D-E719-4296-94A2-01170E603889}.Release|Any CPU.Build.0 = Release|Any CPU
{29CBF617-0334-4DC0-A61E-6F03796AF66F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29CBF617-0334-4DC0-A61E-6F03796AF66F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29CBF617-0334-4DC0-A61E-6F03796AF66F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29CBF617-0334-4DC0-A61E-6F03796AF66F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE