feat: websockets

This commit is contained in:
2022-12-20 12:20:52 -08:00
parent ab85578ccf
commit a5a67963be
24 changed files with 276 additions and 69 deletions
+5 -5
View File
@@ -19,7 +19,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: Ragon.SimpleServer-${{ github.ref }} release_name: Ragon.Relay-${{ github.ref }}
prerelease: true prerelease: true
build: build:
@@ -53,10 +53,10 @@ jobs:
- name: Build - name: Build
shell: bash shell: bash
run: | run: |
release_name="Ragon.SimpleServer-${{ env.TAG }}-${{ matrix.target }}" release_name="Ragon.Relay-${{ env.TAG }}-${{ matrix.target }}"
# Build everything # Build everything
dotnet publish Ragon.SimpleServer/Ragon.SimpleServer.csproj -c Release --runtime "${{ matrix.target }}" -p:PublishSingleFile=true -o "$release_name" dotnet publish Ragon.Relay/Ragon.Relay.csproj -c Release --runtime "${{ matrix.target }}" -p:PublishSingleFile=true -o "$release_name"
# Pack files # Pack files
7z a -tzip "${release_name}.zip" "./${release_name}/*" 7z a -tzip "${release_name}.zip" "./${release_name}/*"
@@ -69,6 +69,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
upload_url: ${{ needs.release.outputs.upload_url }} upload_url: ${{ needs.release.outputs.upload_url }}
asset_path: Ragon.SimpleServer-${{ env.TAG }}-${{ matrix.target }}.zip asset_path: Ragon.Relay-${{ env.TAG }}-${{ matrix.target }}.zip
asset_name: Ragon.SimpleServer-${{ env.TAG }}-${{ matrix.target }}.zip asset_name: Ragon.Relay-${{ env.TAG }}-${{ matrix.target }}.zip
asset_content_type: application/zip asset_content_type: application/zip
+14 -6
View File
@@ -2,6 +2,7 @@ using System.Diagnostics;
using NLog; using NLog;
using Ragon.Common; using Ragon.Common;
using Ragon.Core.Lobby; using Ragon.Core.Lobby;
using Ragon.Core.Server;
using Ragon.Core.Time; using Ragon.Core.Time;
using Ragon.Server; using Ragon.Server;
using Ragon.Server.ENet; using Ragon.Server.ENet;
@@ -13,6 +14,7 @@ public class Application : INetworkListener
private readonly Logger _logger = LogManager.GetCurrentClassLogger(); private readonly Logger _logger = LogManager.GetCurrentClassLogger();
private readonly INetworkServer _server; private readonly INetworkServer _server;
private readonly Thread _dedicatedThread; private readonly Thread _dedicatedThread;
private readonly Executor _executor;
private readonly Configuration _configuration; private readonly Configuration _configuration;
private readonly HandlerRegistry _handlerRegistry; private readonly HandlerRegistry _handlerRegistry;
private readonly ILobby _lobby; private readonly ILobby _lobby;
@@ -22,6 +24,7 @@ public class Application : INetworkListener
public Application(Configuration configuration) public Application(Configuration configuration)
{ {
_configuration = configuration; _configuration = configuration;
_executor = new Executor();
_dedicatedThread = new Thread(Execute); _dedicatedThread = new Thread(Execute);
_dedicatedThread.IsBackground = true; _dedicatedThread.IsBackground = true;
_contexts = new Dictionary<ushort, PlayerContext>(); _contexts = new Dictionary<ushort, PlayerContext>();
@@ -29,20 +32,24 @@ public class Application : INetworkListener
_lobby = new LobbyInMemory(); _lobby = new LobbyInMemory();
_loop = new Loop(); _loop = new Loop();
if (configuration.Socket == "enet") if (configuration.ServerType == "enet")
_server = new ENetServer(); _server = new ENetServer();
if (configuration.ServerType == "websocket")
_server = new NativeWebSocketServer(_executor);
Debug.Assert(_server != null, $"Socket type not supported: {configuration.Socket}. Supported: [enet, websocket]"); Debug.Assert(_server != null, $"Socket type not supported: {configuration.ServerType}. Supported: [enet, websocket]");
} }
public void Execute() public void Execute()
{ {
while (true) while (true)
{ {
_executor.Execute();
_loop.Tick(); _loop.Tick();
_server.Poll(); _server.Poll();
Thread.Sleep((int) 1000.0f / _configuration.SendRate); Thread.Sleep((int)1000.0f / _configuration.ServerTickRate);
} }
} }
@@ -51,7 +58,7 @@ public class Application : INetworkListener
var networkConfiguration = new NetworkConfiguration() var networkConfiguration = new NetworkConfiguration()
{ {
LimitConnections = _configuration.LimitConnections, LimitConnections = _configuration.LimitConnections,
Protocol = RagonVersion.Parse(_configuration.Protocol), Protocol = RagonVersion.Parse(_configuration.GameProtocol),
Address = "0.0.0.0", Address = "0.0.0.0",
Port = _configuration.Port, Port = _configuration.Port,
}; };
@@ -86,9 +93,10 @@ public class Application : INetworkListener
if (room != null) if (room != null)
{ {
room.RemovePlayer(context.RoomPlayer); room.RemovePlayer(context.RoomPlayer);
_lobby.RemoveIfEmpty(room); _lobby.RemoveIfEmpty(room);
} }
context.Dispose(); context.Dispose();
} }
} }
+4 -6
View File
@@ -6,13 +6,11 @@ namespace Ragon.Core;
[Serializable] [Serializable]
public struct Configuration public struct Configuration
{ {
public string Key; public string ServerKey;
public string Protocol; public string ServerType;
public string Socket; public ushort ServerTickRate;
public ushort SendRate; public string GameProtocol;
public ushort Port; public ushort Port;
public int SkipTimeout;
public int ReconnectTimeout;
public int LimitConnections; public int LimitConnections;
public int LimitPlayersPerRoom; public int LimitPlayersPerRoom;
public int LimitRooms; public int LimitRooms;
+9 -9
View File
@@ -54,7 +54,7 @@ public class Entity
writer.WriteData(ref data); writer.WriteData(ref data);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
roomPlayer.Connection.ReliableChannel.Send(sendData); roomPlayer.Connection.Reliable.Send(sendData);
} }
} }
@@ -68,14 +68,14 @@ public class Entity
serializer.WriteUShort(Type); serializer.WriteUShort(Type);
serializer.WriteUShort(Id); serializer.WriteUShort(Id);
serializer.WriteUShort(Owner.Connection.Id); serializer.WriteUShort(Owner.Connection.Id);
ReadOnlySpan<byte> entityPayload = Payload.AsSpan(); ReadOnlySpan<byte> entityPayload = Payload.AsSpan();
serializer.WriteUShort((ushort)entityPayload.Length); serializer.WriteUShort((ushort)entityPayload.Length);
serializer.WriteData(ref entityPayload); serializer.WriteData(ref entityPayload);
var sendData = serializer.ToArray(); var sendData = serializer.ToArray();
foreach (var player in room.ReadyPlayersList) foreach (var player in room.ReadyPlayersList)
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
public void Destroy(byte[] payload) public void Destroy(byte[] payload)
@@ -91,7 +91,7 @@ public class Entity
var sendData = serializer.ToArray(); var sendData = serializer.ToArray();
foreach (var player in room.ReadyPlayersList) foreach (var player in room.ReadyPlayersList)
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
public void ReplicateEvent( public void ReplicateEvent(
@@ -114,7 +114,7 @@ public class Entity
serializer.WriteData(ref payload); serializer.WriteData(ref payload);
var sendData = serializer.ToArray(); var sendData = serializer.ToArray();
targetPlayer.Connection.ReliableChannel.Send(sendData); targetPlayer.Connection.Reliable.Send(sendData);
} }
public void ReplicateEvent( public void ReplicateEvent(
@@ -155,7 +155,7 @@ public class Entity
{ {
case RagonTarget.Owner: case RagonTarget.Owner:
{ {
Owner.Connection.ReliableChannel.Send(sendData); Owner.Connection.Reliable.Send(sendData);
break; break;
} }
case RagonTarget.ExceptOwner: case RagonTarget.ExceptOwner:
@@ -163,7 +163,7 @@ public class Entity
foreach (var roomPlayer in room.ReadyPlayersList) foreach (var roomPlayer in room.ReadyPlayersList)
{ {
if (roomPlayer.Connection.Id != Owner.Connection.Id) if (roomPlayer.Connection.Id != Owner.Connection.Id)
roomPlayer.Connection.ReliableChannel.Send(sendData); roomPlayer.Connection.Reliable.Send(sendData);
} }
break; break;
@@ -173,7 +173,7 @@ public class Entity
foreach (var roomPlayer in room.ReadyPlayersList) foreach (var roomPlayer in room.ReadyPlayersList)
{ {
if (roomPlayer.Connection.Id != caller.Connection.Id) if (roomPlayer.Connection.Id != caller.Connection.Id)
roomPlayer.Connection.ReliableChannel.Send(sendData); roomPlayer.Connection.Reliable.Send(sendData);
} }
break; break;
@@ -181,7 +181,7 @@ public class Entity
case RagonTarget.All: case RagonTarget.All:
{ {
foreach (var roomPlayer in room.ReadyPlayersList) foreach (var roomPlayer in room.ReadyPlayersList)
roomPlayer.Connection.ReliableChannel.Send(sendData); roomPlayer.Connection.Reliable.Send(sendData);
break; break;
} }
} }
+2 -2
View File
@@ -83,7 +83,7 @@ public class Room: IAction
var sendData = Writer.ToArray(); var sendData = Writer.ToArray();
foreach (var roomPlayer in ReadyPlayersList) foreach (var roomPlayer in ReadyPlayersList)
roomPlayer.Connection.UnreliableChannel.Send(sendData); roomPlayer.Connection.Unreliable.Send(sendData);
} }
} }
@@ -161,6 +161,6 @@ public class Room: IAction
public void Broadcast(byte[] data) public void Broadcast(byte[] data)
{ {
foreach (var readyPlayer in ReadyPlayersList) foreach (var readyPlayer in ReadyPlayersList)
readyPlayer.Connection.ReliableChannel.Send(data); readyPlayer.Connection.Reliable.Send(data);
} }
} }
+1 -1
View File
@@ -32,7 +32,7 @@ public sealed class AuthorizationHandler: IHandler
writer.WriteString(playerName); writer.WriteString(playerName);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
context.Connection.ReliableChannel.Send(sendData); context.Connection.Reliable.Send(sendData);
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} authorized"); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} authorized");
} }
+2 -2
View File
@@ -31,7 +31,7 @@ public sealed class CreateHandler: IHandler
writer.WriteString($"Room with id {roomId} already exists"); writer.WriteString($"Room with id {roomId} already exists");
var sendData = writer.ToArray(); var sendData = writer.ToArray();
context.Connection.ReliableChannel.Send(sendData); context.Connection.Reliable.Send(sendData);
_logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} join failed to room {roomId}, room already exist"); _logger.Trace($"Player {context.Connection.Id}|{context.LobbyPlayer.Name} join failed to room {roomId}, room already exist");
return; return;
@@ -79,6 +79,6 @@ public sealed class CreateHandler: IHandler
writer.WriteString(room.Info.Map); writer.WriteString(room.Info.Map);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
} }
+2 -2
View File
@@ -47,7 +47,7 @@ public sealed class JoinHandler : IHandler
writer.WriteString(room.Info.Map); writer.WriteString(room.Info.Map);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
private void JoinFailed(LobbyPlayer player, RagonSerializer writer) private void JoinFailed(LobbyPlayer player, RagonSerializer writer)
@@ -57,6 +57,6 @@ public sealed class JoinHandler : IHandler
writer.WriteString($"Room not exists"); writer.WriteString($"Room not exists");
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
} }
@@ -74,7 +74,7 @@ public sealed class JoinOrCreateHandler : IHandler
writer.WriteString(room.Info.Map); writer.WriteString(room.Info.Map);
var sendData = writer.ToArray(); var sendData = writer.ToArray();
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
_logger.Trace($"Joined to room {room.Id}"); _logger.Trace($"Joined to room {room.Id}");
} }
+2 -2
View File
@@ -88,7 +88,7 @@ public sealed class SceneLoadedHandler : IHandler
foreach (var awaiter in room.ReadyPlayersList) foreach (var awaiter in room.ReadyPlayersList)
{ {
if (awaiter != roomPlayer) if (awaiter != roomPlayer)
awaiter.Connection.ReliableChannel.Send(sendData); awaiter.Connection.Reliable.Send(sendData);
} }
} }
@@ -118,6 +118,6 @@ public sealed class SceneLoadedHandler : IHandler
var sendData = writer.ToArray(); var sendData = writer.ToArray();
foreach (var player in receviersList) foreach (var player in receviersList)
player.Connection.ReliableChannel.Send(sendData); player.Connection.Reliable.Send(sendData);
} }
} }
+1 -1
View File
@@ -14,7 +14,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ragon.Protocol\Ragon.Protocol.csproj" /> <ProjectReference Include="..\Ragon.Protocol\Ragon.Protocol.csproj" />
<ProjectReference Include="..\Ragon.Server.ENet\Ragon.Server.ENet.csproj" /> <ProjectReference Include="..\Ragon.Server.ENet\Ragon.Server.ENet.csproj" />
<ProjectReference Include="..\Ragon.Server.WebSockets\Ragon.Server.WebSockets.csproj" /> <ProjectReference Include="..\Ragon.Server.NativeWebSockets\Ragon.Server.NativeWebSockets.csproj" />
<ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" /> <ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" />
</ItemGroup> </ItemGroup>
+7 -2
View File
@@ -10,12 +10,17 @@ namespace Ragon.Relay
static void Main(string[] args) static void Main(string[] args)
{ {
var logger = LogManager.GetLogger("Ragon.Relay"); var logger = LogManager.GetLogger("Ragon.Relay");
logger.Info("Relay Application"); logger.Info("Relay Application");
var configuration = Configuration.Load("config.json");
var configuration = Configuration.Load("relay.config.json");
var relay = new Application(configuration); var relay = new Application(configuration);
relay.Start();
logger.Info("Started"); logger.Info("Started");
relay.Start();
Console.ReadKey(); Console.ReadKey();
relay.Stop(); relay.Stop();
logger.Info("Stopped"); logger.Info("Stopped");
} }
+1 -1
View File
@@ -14,7 +14,7 @@
<None Update="NLog.config"> <None Update="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<None Update="config.json"> <None Update="relay.config.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
-12
View File
@@ -1,12 +0,0 @@
{
"key": "defaultkey",
"socket": "enet",
"protocol": "1.0.0",
"sendRate": 50,
"port": 4444,
"skipTimeout": 60,
"reconnectTimeout": 300,
"limitConnections": 4095,
"limitPlayersPerRoom": 20,
"limitRooms": 200
}
+10
View File
@@ -0,0 +1,10 @@
{
"serverKey": "defaultkey",
"serverType": "websocket",
"serverTickRate": 20,
"gameProtocol": "1.0.0",
"port": 5000,
"limitConnections": 4095,
"limitPlayersPerRoom": 20,
"limitRooms": 200
}
+4 -4
View File
@@ -5,13 +5,13 @@ namespace Ragon.Server.ENet;
public sealed class ENetConnection: INetworkConnection public sealed class ENetConnection: INetworkConnection
{ {
public ushort Id { get; } public ushort Id { get; }
public INetworkChannel ReliableChannel { get; private set; } public INetworkChannel Reliable { get; private set; }
public INetworkChannel UnreliableChannel { get; private set; } public INetworkChannel Unreliable { get; private set; }
public ENetConnection(Peer peer) public ENetConnection(Peer peer)
{ {
Id = (ushort) peer.ID; Id = (ushort) peer.ID;
ReliableChannel = new ENetReliableChannel(peer, 0); Reliable = new ENetReliableChannel(peer, 0);
UnreliableChannel = new ENetUnreliableChannel(peer, 1); Unreliable = new ENetUnreliableChannel(peer, 1);
} }
} }
+2 -2
View File
@@ -63,7 +63,8 @@ namespace Ragon.Server.ENet
{ {
if (!IsValidProtocol(_event.Data)) if (!IsValidProtocol(_event.Data))
{ {
_logger.Warn("Mismatched protocol, close connection"); _logger.Warn($"Mismatched protocol Server: {RagonVersion.Parse(_protocol)} Client: {RagonVersion.Parse(_event.Data)}, close connection");
_event.Peer.DisconnectNow(0);
break; break;
} }
@@ -109,7 +110,6 @@ namespace Ragon.Server.ENet
private bool IsValidProtocol(uint protocol) private bool IsValidProtocol(uint protocol)
{ {
Console.WriteLine($"{protocol} {_protocol}");
return protocol == _protocol; return protocol == _protocol;
} }
} }
@@ -7,4 +7,12 @@
<RootNamespace>Ragon.WebSockets</RootNamespace> <RootNamespace>Ragon.WebSockets</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ragon.Server\Ragon.Server.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NLog" Version="5.0.5" />
</ItemGroup>
</Project> </Project>
@@ -0,0 +1,44 @@
using System.Net.WebSockets;
using NLog;
namespace Ragon.Server.NativeWebSockets;
public sealed class WebSocketConnection : INetworkConnection
{
private Logger _logger = LogManager.GetCurrentClassLogger();
public ushort Id { get; }
public INetworkChannel Reliable { get; private set; }
public INetworkChannel Unreliable { get; private set; }
public WebSocket Socket { get; private set; }
private WebSocketReliableChannel[] _channels;
public WebSocketConnection(WebSocket webSocket, ushort peerId)
{
Id = peerId;
Socket = webSocket;
var reliableChannel = new WebSocketReliableChannel(webSocket);
var unreliableChannel = new WebSocketReliableChannel(webSocket);
_channels = new[] { reliableChannel, unreliableChannel };
Reliable = reliableChannel;
Unreliable = unreliableChannel;
}
public async Task Flush()
{
foreach (var channel in _channels)
{
try
{
await channel.Flush();
}
catch (Exception ex)
{
_logger.Error(ex);
}
}
}
}
@@ -0,0 +1,27 @@
using System.Net.WebSockets;
using Ragon.Server;
namespace Ragon.Server.NativeWebSockets;
public class WebSocketReliableChannel : INetworkChannel
{
private Queue<byte[]> _queue;
private WebSocket _socket;
public WebSocketReliableChannel(WebSocket webSocket)
{
_socket = webSocket;
_queue = new Queue<byte[]>(512);
}
public void Send(byte[] data)
{
_queue.Enqueue(data);
}
public async Task Flush()
{
while (_queue.TryDequeue(out var sendData) && _socket.State == WebSocketState.Open)
await _socket.SendAsync(sendData, WebSocketMessageType.Binary, WebSocketMessageFlags.EndOfMessage, CancellationToken.None);
}
}
@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.WebSockets;
using NLog;
using Ragon.Common;
using Ragon.Core.Server;
using Ragon.Server;
using Ragon.Server.NativeWebSockets;
namespace Ragon.Core;
public class NativeWebSocketServer : INetworkServer
{
private ILogger _logger = LogManager.GetCurrentClassLogger();
private INetworkListener _networkListener;
private Stack<ushort> _sequencer;
private Executor _executor;
private HttpListener _httpListener;
private WebSocketConnection[] _connections;
private ushort _lastPeerId;
private CancellationTokenSource _cancellationTokenSource;
public NativeWebSocketServer(Executor executor)
{
_sequencer = new Stack<ushort>();
_connections = Array.Empty<WebSocketConnection>();
_executor = executor;
}
public async Task StartAccept(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var context = await _httpListener.GetContextAsync();
if (!context.Request.IsWebSocketRequest) continue;
var webSocketContext = await context.AcceptWebSocketAsync(null);
var webSocket = webSocketContext.WebSocket;
var peerId = _sequencer.Pop();
var connection = new WebSocketConnection(webSocket, peerId);
_lastPeerId = peerId;
_connections[peerId] = connection;
_networkListener.OnConnected(connection);
_executor.Run(StartListen(connection, cancellationToken));
}
}
async Task StartListen(WebSocketConnection connection, CancellationToken cancellationToken)
{
var webSocket = connection.Socket;
var bytes = new byte[2048];
var buffer = new Memory<byte>(bytes);
while (
webSocket.State == WebSocketState.Open ||
!cancellationToken.IsCancellationRequested)
{
try
{
var result = await webSocket.ReceiveAsync(buffer, cancellationToken);
var dataRaw = buffer.Slice(0, result.Count);
_networkListener.OnData(connection, dataRaw.ToArray());
}
catch (Exception ex)
{
break;
}
}
_sequencer.Push(connection.Id);
_networkListener.OnDisconnected(connection);
}
public async void Poll()
{
foreach (var conn in _connections)
{
if (conn != null)
{
await conn.Flush();
}
}
}
public void Start(
INetworkListener listener,
NetworkConfiguration configuration
)
{
_networkListener = listener;
_cancellationTokenSource = new CancellationTokenSource();
var limit = (ushort) configuration.LimitConnections;
for (ushort i = limit; i != 0; i--)
_sequencer.Push(i);
_sequencer.Push(0);
_connections = new WebSocketConnection[configuration.LimitConnections];
_httpListener = new HttpListener();
_httpListener.Prefixes.Add($"http://127.0.0.1:{configuration.Port}/");
_httpListener.Start();
_executor.Run(StartAccept(_cancellationTokenSource.Token));
var protocolDecoded = RagonVersion.Parse(configuration.Protocol);
_logger.Info($"Network listening on http://*:{configuration.Port}/");
_logger.Info($"Protocol: {protocolDecoded}");
}
public void Stop()
{
_cancellationTokenSource.Cancel();
_httpListener.Stop();
}
}
+2 -2
View File
@@ -3,6 +3,6 @@ namespace Ragon.Server;
public interface INetworkConnection public interface INetworkConnection
{ {
public ushort Id { get; } public ushort Id { get; }
public INetworkChannel ReliableChannel { get; } public INetworkChannel Reliable { get; }
public INetworkChannel UnreliableChannel { get; } public INetworkChannel Unreliable { get; }
} }
@@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
using System.Threading.Channels; using System.Threading.Channels;
using System.Threading.Tasks;
using NLog.LayoutRenderers.Wrappers;
namespace Ragon.Core; namespace Ragon.Core.Server;
public class Executor: TaskScheduler public class Executor: TaskScheduler
{ {
private ChannelReader<Task> _reader; private ChannelReader<Task> _reader;
private ChannelWriter<Task> _writer; private ChannelWriter<Task> _writer;
private Queue<Task> _pendingTasks; private Queue<Task> _pendingTasks;
private TaskFactory _taskFactory;
public void Run(Task task) public void Run(Task task)
{ {
task.Start(this); _taskFactory.StartNew(() => task);
} }
public Executor() public Executor()
@@ -22,7 +19,8 @@ public class Executor: TaskScheduler
var channel = Channel.CreateUnbounded<Task>(); var channel = Channel.CreateUnbounded<Task>();
_reader = channel.Reader; _reader = channel.Reader;
_writer = channel.Writer; _writer = channel.Writer;
_taskFactory = new TaskFactory(this);
_pendingTasks = new Queue<Task>(); _pendingTasks = new Queue<Task>();
} }
+1 -1
View File
@@ -8,7 +8,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server", "Ragon.Serve
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Core", "Ragon.Core\Ragon.Core.csproj", "{F4AA86B9-2486-4B53-BA77-43D958A2FDC3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Core", "Ragon.Core\Ragon.Core.csproj", "{F4AA86B9-2486-4B53-BA77-43D958A2FDC3}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.WebSockets", "Ragon.Server.WebSockets\Ragon.Server.WebSockets.csproj", "{81050343-A9B8-487B-86C8-7A5B7DD9C39B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.NativeWebSockets", "Ragon.Server.NativeWebSockets\Ragon.Server.NativeWebSockets.csproj", "{81050343-A9B8-487B-86C8-7A5B7DD9C39B}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.ENet", "Ragon.Server.ENet\Ragon.Server.ENet.csproj", "{DD79AC4F-9E5C-4938-850E-805D537E68D0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ragon.Server.ENet", "Ragon.Server.ENet\Ragon.Server.ENet.csproj", "{DD79AC4F-9E5C-4938-850E-805D537E68D0}"
EndProject EndProject