[성현모] Http, Socket 통신 추가
This commit is contained in:
Binary file not shown.
Binary file not shown.
@ -6,4 +6,14 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\HubX.Library.DB\HubX.Library.DB.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="SystemX.Core">
|
||||
<HintPath>..\..\DLL\SystemX.Core.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
29
Projects/HubX/HubX.Library/Socket/Object/Client.cs
Normal file
29
Projects/HubX/HubX.Library/Socket/Object/Client.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using HubX.Library.Socket.Session;
|
||||
|
||||
namespace HubX.Library.Socket.Object
|
||||
{
|
||||
public class Client
|
||||
{
|
||||
|
||||
public EnumObjectType ObjectType = EnumObjectType.Client;
|
||||
|
||||
private int ClientId;
|
||||
public int Id
|
||||
{
|
||||
get { return ClientId; }
|
||||
set { ClientId = value; }
|
||||
}
|
||||
|
||||
public ClientSession Session { get; set; }
|
||||
|
||||
public Client()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Projects/HubX/HubX.Library/Socket/Object/EnumObjectType.cs
Normal file
14
Projects/HubX/HubX.Library/Socket/Object/EnumObjectType.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HubX.Library.Socket.Object
|
||||
{
|
||||
public enum EnumObjectType
|
||||
{
|
||||
NONE = 0,
|
||||
Client = 1,
|
||||
}
|
||||
}
|
||||
80
Projects/HubX/HubX.Library/Socket/Object/ObjectManager.cs
Normal file
80
Projects/HubX/HubX.Library/Socket/Object/ObjectManager.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HubX.Library.Socket.Object
|
||||
{
|
||||
public class ObjectManager
|
||||
{
|
||||
public static ObjectManager Instance { get; } = new ObjectManager();
|
||||
|
||||
object _lock = new object();
|
||||
Dictionary<int, Client> _players = new Dictionary<int, Client>();
|
||||
|
||||
// [UNUSED(1)][TYPE(7)][ID(24)]
|
||||
int _counter = 0;
|
||||
|
||||
public T Add<T>() where T : Client, new()
|
||||
{
|
||||
T gameObject = new T();
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
gameObject.Id = GenerateId(gameObject.ObjectType);
|
||||
|
||||
if (gameObject.ObjectType == EnumObjectType.Client)
|
||||
{
|
||||
_players.Add(gameObject.Id, gameObject as Client);
|
||||
}
|
||||
}
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
int GenerateId(EnumObjectType type)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return ((int)type << 24) | (_counter++);
|
||||
}
|
||||
}
|
||||
|
||||
public static EnumObjectType GetObjectTypeById(int id)
|
||||
{
|
||||
int type = (id >> 24) & 0x7F;
|
||||
return (EnumObjectType)type;
|
||||
}
|
||||
|
||||
public bool Remove(int objectId)
|
||||
{
|
||||
EnumObjectType objectType = GetObjectTypeById(objectId);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (objectType == EnumObjectType.Client)
|
||||
return _players.Remove(objectId);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Client Find(int objectId)
|
||||
{
|
||||
EnumObjectType objectType = GetObjectTypeById(objectId);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (objectType == EnumObjectType.Client)
|
||||
{
|
||||
Client player = null;
|
||||
if (_players.TryGetValue(objectId, out player))
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Projects/HubX/HubX.Library/Socket/Packet/EnumMessageId.cs
Normal file
33
Projects/HubX/HubX.Library/Socket/Packet/EnumMessageId.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HubX.Library.Socket.Packet
|
||||
{
|
||||
public enum EnumMessageId
|
||||
{
|
||||
//C2S : Client to Server
|
||||
//S2C : Server to Client
|
||||
|
||||
//unique key CRUD
|
||||
C2S_INSERT_UniqueKey = 10,
|
||||
S2C_INSERT_UniqueKey = 11,
|
||||
C2S_SELECT_UniqueKey = 12,
|
||||
S2C_SELECT_UniqueKey = 13,
|
||||
C2S_UPDATE_UniqueKey = 14,
|
||||
S2C_UPDATE_UniqueKey = 15,
|
||||
C2S_DELETE_UniqueKey = 16,
|
||||
S2C_DELETE_UniqueKey = 17,
|
||||
}
|
||||
|
||||
public enum EnumMessageResult
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Success = 10,
|
||||
Failed = 10,
|
||||
Error = 11,
|
||||
}
|
||||
}
|
||||
43
Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs
Normal file
43
Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using HubX.Library.Socket.Object;
|
||||
using HubX.Library.Socket.Session;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Core.Communication;
|
||||
|
||||
namespace HubX.Library.Socket.Packet
|
||||
{
|
||||
|
||||
public class PacketHandler
|
||||
{
|
||||
public static void C2S_INSERT_UniqueKeyHandler(PacketSession session, IMessage packet)
|
||||
{
|
||||
C2S_INSERT_UniqueKey movePacket = packet as C2S_INSERT_UniqueKey;
|
||||
ClientSession clientSession = session as ClientSession;
|
||||
|
||||
Client client = clientSession.Client;
|
||||
if (client == null)
|
||||
return;
|
||||
}
|
||||
|
||||
public static void C_SkillHandler(PacketSession session, IMessage packet)
|
||||
{
|
||||
//C_Skill skillPacket = packet as C_Skill;
|
||||
//ClientSession clientSession = session as ClientSession;
|
||||
|
||||
//Player player = clientSession.MyPlayer;
|
||||
//if (player == null)
|
||||
// return;
|
||||
|
||||
//GameRoom room = player.Room;
|
||||
//if (room == null)
|
||||
// return;
|
||||
|
||||
//room.Push(room.HandleSkill, player, skillPacket);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
46
Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs
Normal file
46
Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HubX.Library.Socket.Packet
|
||||
{
|
||||
public interface IMessage
|
||||
{
|
||||
}
|
||||
|
||||
public class C2S : IMessage
|
||||
{
|
||||
public EnumMessageId MessageId { get; set; }
|
||||
}
|
||||
|
||||
public class S2C : IMessage
|
||||
{
|
||||
public EnumMessageId MessageId { get; set; }
|
||||
|
||||
public EnumMessageResult Result { get; set; }
|
||||
}
|
||||
|
||||
public sealed class C2S_INSERT_UniqueKey : C2S
|
||||
{
|
||||
public string Identity { get; set; }
|
||||
|
||||
public string Data1 { get; set; }
|
||||
public string Data2 { get; set; }
|
||||
public string Data3 { get; set; }
|
||||
public string Data4 { get; set; }
|
||||
public string Data5 { get; set; }
|
||||
}
|
||||
|
||||
public sealed class S2C_INSERT_UniqueKey : S2C
|
||||
{
|
||||
public string Identity { get; set; }
|
||||
|
||||
public string Data1 { get; set; }
|
||||
public string Data2 { get; set; }
|
||||
public string Data3 { get; set; }
|
||||
public string Data4 { get; set; }
|
||||
public string Data5 { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Core.Communication;
|
||||
|
||||
namespace HubX.Library.Socket.Packet
|
||||
{
|
||||
public class PacketManager
|
||||
{
|
||||
#region Singleton
|
||||
static PacketManager _instance = new PacketManager();
|
||||
public static PacketManager Instance { get { return _instance; } }
|
||||
#endregion
|
||||
|
||||
PacketManager()
|
||||
{
|
||||
Register();
|
||||
}
|
||||
|
||||
Dictionary<ushort, Action<PacketSession, ArraySegment<byte>, ushort>> _onRecv = new Dictionary<ushort, Action<PacketSession, ArraySegment<byte>, ushort>>();
|
||||
Dictionary<ushort, Action<PacketSession, IMessage>> _handler = new Dictionary<ushort, Action<PacketSession, IMessage>>();
|
||||
|
||||
public Action<PacketSession, IMessage, ushort> CustomHandler { get; set; }
|
||||
|
||||
public void Register()
|
||||
{
|
||||
_onRecv.Add((ushort)EnumMessageId.C2S_INSERT_UniqueKey, MakePacket<C2S_INSERT_UniqueKey>);
|
||||
_handler.Add((ushort)EnumMessageId.C2S_INSERT_UniqueKey, PacketHandler.C2S_INSERT_UniqueKeyHandler);
|
||||
}
|
||||
|
||||
public void OnRecvPacket(PacketSession session, ArraySegment<byte> buffer)
|
||||
{
|
||||
ushort count = 0;
|
||||
|
||||
ushort size = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
|
||||
count += 2;
|
||||
ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + count);
|
||||
count += 2;
|
||||
|
||||
Action<PacketSession, ArraySegment<byte>, ushort> action = null;
|
||||
if (_onRecv.TryGetValue(id, out action))
|
||||
action.Invoke(session, buffer, id);
|
||||
}
|
||||
|
||||
void MakePacket<T>(PacketSession session, ArraySegment<byte> buffer, ushort id) where T : IMessage, new()
|
||||
{
|
||||
T pkt = new T();
|
||||
//pkt.MergeFrom(buffer.Array, buffer.Offset + 4, buffer.Count - 4);
|
||||
|
||||
if (CustomHandler != null)
|
||||
{
|
||||
CustomHandler.Invoke(session, pkt, id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Action<PacketSession, IMessage> action = null;
|
||||
if (_handler.TryGetValue(id, out action))
|
||||
action.Invoke(session, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
public Action<PacketSession, IMessage> GetPacketHandler(ushort id)
|
||||
{
|
||||
Action<PacketSession, IMessage> action = null;
|
||||
if (_handler.TryGetValue(id, out action))
|
||||
return action;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Projects/HubX/HubX.Library/Socket/Session/ClientSession.cs
Normal file
56
Projects/HubX/HubX.Library/Socket/Session/ClientSession.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using HubX.Library.Socket.Object;
|
||||
using HubX.Library.Socket.Packet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Core.Communication;
|
||||
|
||||
namespace HubX.Library.Socket.Session
|
||||
{
|
||||
public class ClientSession : PacketSession
|
||||
{
|
||||
public Client Client { get; set; }
|
||||
public int SessionId { get; set; }
|
||||
|
||||
public void Send(IMessage packet)
|
||||
{
|
||||
//string msgName = packet.Descriptor.Name.Replace("_", string.Empty);
|
||||
//EnumMessageId msgId = (EnumMessageId)Enum.Parse(typeof(EnumMessageId), msgName);
|
||||
//ushort size = (ushort)packet.CalculateSize();
|
||||
//byte[] sendBuffer = new byte[size + 4];
|
||||
//Array.Copy(BitConverter.GetBytes((ushort)(size + 4)), 0, sendBuffer, 0, sizeof(ushort));
|
||||
//Array.Copy(BitConverter.GetBytes((ushort)msgId), 0, sendBuffer, 2, sizeof(ushort));
|
||||
//Array.Copy(packet.ToByteArray(), 0, sendBuffer, 4, size);
|
||||
//Send(new ArraySegment<byte>(sendBuffer));
|
||||
}
|
||||
|
||||
public override void OnConnected(EndPoint endPoint)
|
||||
{
|
||||
Log4net.WriteLine($"OnConnected : {endPoint}", LogType.SOCKET);
|
||||
Client = ObjectManager.Instance.Add<Client>();
|
||||
{
|
||||
Client.Session = this;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnRecvPacket(ArraySegment<byte> buffer)
|
||||
{
|
||||
Log4net.WriteLine($"OnRecvPacket : {Encoding.UTF8.GetString(buffer)}", LogType.SOCKET);
|
||||
PacketManager.Instance.OnRecvPacket(this, buffer);
|
||||
}
|
||||
|
||||
public override void OnDisconnected(EndPoint endPoint)
|
||||
{
|
||||
Log4net.WriteLine($"OnDisconnected : {endPoint}", LogType.SOCKET);
|
||||
}
|
||||
|
||||
public override void OnSend(int numOfBytes)
|
||||
{
|
||||
//Console.WriteLine($"Transferred bytes: {numOfBytes}");
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Projects/HubX/HubX.Library/Socket/Session/SessionManager.cs
Normal file
54
Projects/HubX/HubX.Library/Socket/Session/SessionManager.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using HubX.Library.Socket.Packet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Core.Communication;
|
||||
|
||||
namespace HubX.Library.Socket.Session
|
||||
{
|
||||
public class SessionManager
|
||||
{
|
||||
static SessionManager _session = new SessionManager();
|
||||
public static SessionManager Instance { get { return _session; } }
|
||||
|
||||
int _sessionId = 0;
|
||||
Dictionary<int, ClientSession> _sessions = new Dictionary<int, ClientSession>();
|
||||
object _lock = new object();
|
||||
|
||||
public ClientSession Generate()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
int sessionId = ++_sessionId;
|
||||
|
||||
ClientSession session = new ClientSession();
|
||||
session.SessionId = sessionId;
|
||||
_sessions.Add(sessionId, session);
|
||||
|
||||
Log4net.WriteLine($"Connected : {sessionId}", LogType.SOCKET);
|
||||
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
public ClientSession Find(int id)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
ClientSession session = null;
|
||||
_sessions.TryGetValue(id, out session);
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
public void Remove(ClientSession session)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_sessions.Remove(session.SessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,10 +6,22 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<WarningLevel>9999</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<WarningLevel>9999</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\HubX.Library\HubX.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="SystemX.Core">
|
||||
<HintPath>..\..\DLL\SystemX.Core.dll</HintPath>
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using SystemX.Core.Log4net;
|
||||
using HubX.Library.Socket.Session;
|
||||
using HubX.Server;
|
||||
using System.Net;
|
||||
using SystemX.Core.Communication;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -21,6 +24,30 @@ if (app.Environment.IsDevelopment())
|
||||
Log4net.WriteLine("Run");
|
||||
Log4net.WriteLine("Custom LogLevel",LogType.DB);
|
||||
|
||||
WeatherForecast weatherForecast = new WeatherForecast();
|
||||
weatherForecast.Summary = "so hot";
|
||||
var strJson = weatherForecast.ToJson();
|
||||
|
||||
var deep = weatherForecast.DeepCopy();
|
||||
deep.Summary = "so cool";
|
||||
|
||||
var rr = strJson.ToObject<WeatherForecast>();
|
||||
|
||||
Task.Run(async() =>
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
Listener _listener = new Listener();
|
||||
|
||||
// string host = Dns.GetHostName();
|
||||
IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1");
|
||||
IPAddress ipAddr = ipHost.AddressList[0];
|
||||
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
|
||||
|
||||
_listener.Init(endPoint, () => { return SessionManager.Instance.Generate(); });
|
||||
|
||||
Console.WriteLine("Listening...");
|
||||
});
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
@ -1,4 +1,31 @@
|
||||
{
|
||||
{
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5103"
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "https://localhost:7163;http://localhost:5103"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
@ -7,35 +34,5 @@
|
||||
"applicationUrl": "http://localhost:33125",
|
||||
"sslPort": 44383
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5103",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7163;http://localhost:5103",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Projects/SystemX.Core/SystemX.Core/Communication/Http.cs
Normal file
112
Projects/SystemX.Core/SystemX.Core/Communication/Http.cs
Normal file
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.Communication
|
||||
{
|
||||
public class Http
|
||||
{
|
||||
/// <summary>
|
||||
/// PostJsonAsync
|
||||
/// </summary>
|
||||
/// <param name="url">https://127.0.0.1:443</param>
|
||||
/// <param name="timeOutSeconds">Range 5~30 secconds</param>
|
||||
public virtual async Task<RESPONSE?> PostJsonAsync<REQUEST, RESPONSE>(string url, REQUEST request, short timeOutSeconds = 5) where REQUEST : class where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
int retry = 0;
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
try
|
||||
{
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{url}");
|
||||
|
||||
Log4net.WriteLine($"[POST] Request({guid})::{url}{Environment.NewLine}{request?.ToJson()}", LogType.HTTP);
|
||||
|
||||
DateTime requestTime = DateTime.Now;
|
||||
var res = await httpClient.PostAsJsonAsync(url, request);
|
||||
response = await res.Content.ReadFromJsonAsync<RESPONSE>();
|
||||
|
||||
Log4net.WriteLine($"[POST] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}{Environment.NewLine}{response?.ToJson()}", LogType.HTTP);
|
||||
break;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
retry += 1;
|
||||
}
|
||||
|
||||
if (retry > 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetJsonAsnyc
|
||||
/// </summary>
|
||||
/// <param name="url">https://127.0.0.1:443</param>
|
||||
/// <param name="timeOutSeconds">Range 5~30 secconds</param>
|
||||
public virtual async Task<RESPONSE?> GetJsonAsync<RESPONSE>(string url, short timeOutSeconds = 10) where RESPONSE : class
|
||||
{
|
||||
RESPONSE? response = default(RESPONSE);
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{url}");
|
||||
|
||||
Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.HTTP);
|
||||
|
||||
DateTime requestTime = DateTime.Now;
|
||||
response = await httpClient.GetFromJsonAsync<RESPONSE>(url);
|
||||
|
||||
Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.HTTP);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
protected HttpClientHandler GetClientHandler()
|
||||
{
|
||||
HttpClientHandler clientHandler = new HttpClientHandler();
|
||||
clientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
return clientHandler;
|
||||
}
|
||||
|
||||
protected short SetTimeout(short timeOutSeconds)
|
||||
{
|
||||
short timeoutMin = 5;
|
||||
short timeoutMax = 30;
|
||||
|
||||
timeOutSeconds = Math.Clamp(timeOutSeconds, timeoutMin, timeoutMax);
|
||||
|
||||
return timeOutSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static System.Collections.Specialized.BitVector32;
|
||||
|
||||
namespace SystemX.Core.Communication
|
||||
{
|
||||
public class Listener
|
||||
{
|
||||
Socket _listenSocket;
|
||||
Func<Session> _sessionFactory;
|
||||
|
||||
public void Init(IPEndPoint endPoint, Func<Session> sessionFactory, int register = 10, int backlog = 100)
|
||||
{
|
||||
_listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
_sessionFactory += sessionFactory;
|
||||
|
||||
_listenSocket.Bind(endPoint);
|
||||
|
||||
// backlog : 최대 대기수
|
||||
_listenSocket.Listen(backlog);
|
||||
|
||||
for (int i = 0; i < register; i++)
|
||||
{
|
||||
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
|
||||
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
|
||||
RegisterAccept(args);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterAccept(SocketAsyncEventArgs args)
|
||||
{
|
||||
args.AcceptSocket = null;
|
||||
|
||||
bool pending = _listenSocket.AcceptAsync(args);
|
||||
if (pending == false)
|
||||
OnAcceptCompleted(null, args);
|
||||
}
|
||||
|
||||
void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
|
||||
{
|
||||
if (args.SocketError == SocketError.Success)
|
||||
{
|
||||
Session session = _sessionFactory.Invoke();
|
||||
session.Start(args.AcceptSocket);
|
||||
session.OnConnected(args.AcceptSocket.RemoteEndPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log4net.WriteLine(args.SocketError.ToString(), LogType.Error);
|
||||
}
|
||||
|
||||
RegisterAccept(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.Communication
|
||||
{
|
||||
public class RecvBuffer
|
||||
{
|
||||
// [r][][w][][][][][][][]
|
||||
ArraySegment<byte> _buffer;
|
||||
int _readPos;
|
||||
int _writePos;
|
||||
|
||||
public RecvBuffer(int bufferSize)
|
||||
{
|
||||
_buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize);
|
||||
}
|
||||
|
||||
public int DataSize { get { return _writePos - _readPos; } }
|
||||
public int FreeSize { get { return _buffer.Count - _writePos; } }
|
||||
|
||||
public ArraySegment<byte> ReadSegment
|
||||
{
|
||||
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _readPos, DataSize); }
|
||||
}
|
||||
|
||||
public ArraySegment<byte> WriteSegment
|
||||
{
|
||||
get { return new ArraySegment<byte>(_buffer.Array, _buffer.Offset + _writePos, FreeSize); }
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
int dataSize = DataSize;
|
||||
if (dataSize == 0)
|
||||
{
|
||||
// 남은 데이터가 없으면 복사하지 않고 커서 위치만 리셋
|
||||
_readPos = _writePos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 남은 찌끄레기가 있으면 시작 위치로 복사
|
||||
Array.Copy(_buffer.Array, _buffer.Offset + _readPos, _buffer.Array, _buffer.Offset, dataSize);
|
||||
_readPos = 0;
|
||||
_writePos = dataSize;
|
||||
}
|
||||
}
|
||||
|
||||
public bool OnRead(int numOfBytes)
|
||||
{
|
||||
if (numOfBytes > DataSize)
|
||||
return false;
|
||||
|
||||
_readPos += numOfBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OnWrite(int numOfBytes)
|
||||
{
|
||||
if (numOfBytes > FreeSize)
|
||||
return false;
|
||||
|
||||
_writePos += numOfBytes;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.Communication
|
||||
{
|
||||
public abstract class PacketSession : Session
|
||||
{
|
||||
public static readonly int HeaderSize = 2;
|
||||
|
||||
// [size(2)][packetId(2)][ ... ][size(2)][packetId(2)][ ... ]
|
||||
public sealed override int OnRecv(ArraySegment<byte> buffer)
|
||||
{
|
||||
int processLen = 0;
|
||||
int packetCount = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// 최소한 헤더는 파싱할 수 있는지 확인
|
||||
if (buffer.Count < HeaderSize)
|
||||
break;
|
||||
|
||||
// 패킷이 완전체로 도착했는지 확인
|
||||
ushort dataSize = BitConverter.ToUInt16(buffer.Array, buffer.Offset);
|
||||
if (buffer.Count < dataSize)
|
||||
break;
|
||||
|
||||
// 여기까지 왔으면 패킷 조립 가능
|
||||
OnRecvPacket(new ArraySegment<byte>(buffer.Array, buffer.Offset, dataSize));
|
||||
packetCount++;
|
||||
|
||||
processLen += dataSize;
|
||||
buffer = new ArraySegment<byte>(buffer.Array, buffer.Offset + dataSize, buffer.Count - dataSize);
|
||||
}
|
||||
|
||||
return processLen;
|
||||
}
|
||||
|
||||
public abstract void OnRecvPacket(ArraySegment<byte> buffer);
|
||||
}
|
||||
|
||||
public abstract class Session
|
||||
{
|
||||
Socket _socket;
|
||||
int _disconnected = 0;
|
||||
|
||||
RecvBuffer _recvBuffer = new RecvBuffer(65535);
|
||||
|
||||
object _lock = new object();
|
||||
Queue<ArraySegment<byte>> _sendQueue = new Queue<ArraySegment<byte>>();
|
||||
List<ArraySegment<byte>> _pendingList = new List<ArraySegment<byte>>();
|
||||
SocketAsyncEventArgs _sendArgs = new SocketAsyncEventArgs();
|
||||
SocketAsyncEventArgs _recvArgs = new SocketAsyncEventArgs();
|
||||
|
||||
public abstract void OnConnected(EndPoint endPoint);
|
||||
public abstract int OnRecv(ArraySegment<byte> buffer);
|
||||
public abstract void OnSend(int numOfBytes);
|
||||
public abstract void OnDisconnected(EndPoint endPoint);
|
||||
|
||||
void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_sendQueue.Clear();
|
||||
_pendingList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Start(Socket socket)
|
||||
{
|
||||
Log4net.WriteLine("Session Start");
|
||||
|
||||
_socket = socket;
|
||||
|
||||
_recvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnRecvCompleted);
|
||||
_sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
|
||||
|
||||
RegisterRecv();
|
||||
}
|
||||
|
||||
public void Send(List<ArraySegment<byte>> sendBuffList)
|
||||
{
|
||||
if (sendBuffList.Count == 0)
|
||||
return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (ArraySegment<byte> sendBuff in sendBuffList)
|
||||
_sendQueue.Enqueue(sendBuff);
|
||||
|
||||
if (_pendingList.Count == 0)
|
||||
RegisterSend();
|
||||
}
|
||||
}
|
||||
|
||||
public void Send(ArraySegment<byte> sendBuff)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_sendQueue.Enqueue(sendBuff);
|
||||
if (_pendingList.Count == 0)
|
||||
RegisterSend();
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
if (Interlocked.Exchange(ref _disconnected, 1) == 1)
|
||||
return;
|
||||
|
||||
OnDisconnected(_socket.RemoteEndPoint);
|
||||
_socket.Shutdown(SocketShutdown.Both);
|
||||
_socket.Close();
|
||||
Clear();
|
||||
}
|
||||
|
||||
#region 네트워크 통신
|
||||
|
||||
void RegisterSend()
|
||||
{
|
||||
if (_disconnected == 1)
|
||||
return;
|
||||
|
||||
while (_sendQueue.Count > 0)
|
||||
{
|
||||
ArraySegment<byte> buff = _sendQueue.Dequeue();
|
||||
_pendingList.Add(buff);
|
||||
}
|
||||
_sendArgs.BufferList = _pendingList;
|
||||
|
||||
try
|
||||
{
|
||||
bool pending = _socket.SendAsync(_sendArgs);
|
||||
if (pending == false)
|
||||
OnSendCompleted(null, _sendArgs);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine($"RegisterSend Failed {e}", LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
void OnSendCompleted(object sender, SocketAsyncEventArgs args)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success)
|
||||
{
|
||||
try
|
||||
{
|
||||
_sendArgs.BufferList = null;
|
||||
_pendingList.Clear();
|
||||
|
||||
OnSend(_sendArgs.BytesTransferred);
|
||||
|
||||
if (_sendQueue.Count > 0)
|
||||
RegisterSend();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine($"OnSendCompleted Failed {e}", LogType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterRecv()
|
||||
{
|
||||
if (_disconnected == 1)
|
||||
return;
|
||||
|
||||
_recvBuffer.Clean();
|
||||
ArraySegment<byte> segment = _recvBuffer.WriteSegment;
|
||||
_recvArgs.SetBuffer(segment.Array, segment.Offset, segment.Count);
|
||||
|
||||
try
|
||||
{
|
||||
bool pending = _socket.ReceiveAsync(_recvArgs);
|
||||
if (pending == false)
|
||||
OnRecvCompleted(null, _recvArgs);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine($"RegisterRecv Failed {e}", LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
void OnRecvCompleted(object sender, SocketAsyncEventArgs args)
|
||||
{
|
||||
if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Write 커서 이동
|
||||
if (_recvBuffer.OnWrite(args.BytesTransferred) == false)
|
||||
{
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// 컨텐츠 쪽으로 데이터를 넘겨주고 얼마나 처리했는지 받는다
|
||||
int processLen = OnRecv(_recvBuffer.ReadSegment);
|
||||
if (processLen < 0 || _recvBuffer.DataSize < processLen)
|
||||
{
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read 커서 이동
|
||||
if (_recvBuffer.OnRead(processLen) == false)
|
||||
{
|
||||
Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
RegisterRecv();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine($"OnRecvCompleted Failed {e}", LogType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
33
Projects/SystemX.Core/SystemX.Core/DB/DataBase.cs
Normal file
33
Projects/SystemX.Core/SystemX.Core/DB/DataBase.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.DB
|
||||
{
|
||||
public class DataBase
|
||||
{
|
||||
[JsonPropertyName("IP")]
|
||||
public string? IP { get; set; }
|
||||
|
||||
[JsonPropertyName("Port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[JsonPropertyName("DBName")]
|
||||
public string? DBName { get; set; }
|
||||
|
||||
[JsonPropertyName("DBID")]
|
||||
public int DBID { get; set; }
|
||||
|
||||
[JsonPropertyName("DBContext")]
|
||||
public string? DBContext { get; set; }
|
||||
|
||||
[JsonPropertyName("UserID")]
|
||||
public string? UserID { get; set; }
|
||||
|
||||
[JsonPropertyName("Password")]
|
||||
public string? Password { get; set; }
|
||||
}
|
||||
}
|
||||
106
Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs
Normal file
106
Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.DB
|
||||
{
|
||||
public static class EFCore
|
||||
{
|
||||
/// <summary>
|
||||
/// Get SqlServer Connection String
|
||||
/// </summary>
|
||||
public static string ConvertToConnectionString(this DataBase dbConfig)
|
||||
{
|
||||
return $"server={dbConfig.IP},{dbConfig.Port}; user id={dbConfig.UserID}; password={dbConfig.Password}; database={dbConfig.DBName}; TrustServerCertificate=true;";
|
||||
}
|
||||
|
||||
public static IEnumerable<TEntity>? GetEntity<TEntity>(this DbContext dbContext) where TEntity : class
|
||||
{
|
||||
IEnumerable<TEntity>? entity = default;
|
||||
|
||||
var type = dbContext.GetType();
|
||||
try
|
||||
{
|
||||
foreach (var prop in type.GetProperties())
|
||||
{
|
||||
string propertyFullName = $"{prop.PropertyType.FullName}";
|
||||
if (propertyFullName.ToLower().Contains(typeof(TEntity).Name.ToLower()))
|
||||
{
|
||||
entity = prop.GetValue(dbContext) as IEnumerable<TEntity>;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log4net.WriteLine(ex);
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
#region Transaction
|
||||
public static IDbContextTransaction CreateTransaction(this DbContext dbContext)
|
||||
{
|
||||
return dbContext.Database.BeginTransaction();
|
||||
}
|
||||
|
||||
public static bool CloseTransaction(this DbContext dbContext, IDbContextTransaction transaction)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
dbContext.SaveChanges();
|
||||
transaction.Commit();
|
||||
result = true;
|
||||
|
||||
Log4net.WriteLine("Transaction Commit", LogType.Debug);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
transaction.Rollback();
|
||||
Log4net.WriteLine("Transaction Rollback", LogType.Error);
|
||||
Log4net.WriteLine(ex);
|
||||
}
|
||||
transaction.Dispose();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Transaction Async
|
||||
public static async Task<IDbContextTransaction> CreateTransactionAsync(this DbContext dbContext)
|
||||
{
|
||||
return await dbContext.Database.BeginTransactionAsync();
|
||||
}
|
||||
|
||||
public static async Task<bool> CloseTransactionAsync(this DbContext dbContext, IDbContextTransaction transaction)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
await dbContext.SaveChangesAsync();
|
||||
await transaction.CommitAsync();
|
||||
result = true;
|
||||
|
||||
Log4net.WriteLine("Transaction Commit", LogType.Debug);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
Log4net.WriteLine("Transaction Rollback", LogType.Error);
|
||||
Log4net.WriteLine(ex);
|
||||
}
|
||||
await transaction.DisposeAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -7,8 +7,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemX.Core.Log4net
|
||||
{
|
||||
|
||||
#region LogType
|
||||
public enum LogType
|
||||
{
|
||||
@ -240,7 +239,7 @@ namespace SystemX.Core.Log4net
|
||||
</configuration>";
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
log4net 지정 가능 색상
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="log4net" Version="3.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
15
Projects/SystemX.Core/SystemX.Core/Utils/DateTimeUtils.cs
Normal file
15
Projects/SystemX.Core/SystemX.Core/Utils/DateTimeUtils.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public static class DateTimeUtils
|
||||
{
|
||||
public static long ToUnixTime(this DateTime dateTime)
|
||||
{
|
||||
DateTimeOffset dto = new DateTimeOffset(dateTime.ToUniversalTime());
|
||||
return dto.ToUnixTimeSeconds();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SystemX.Core.Log4net;
|
||||
|
||||
public static class JsonUtils
|
||||
{
|
||||
Reference in New Issue
Block a user