Skip to content

Commit 6d79468

Browse files
committed
1 parent c35d26d commit 6d79468

19 files changed

+1622
-0
lines changed
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using Microsoft.Extensions.Hosting;
5+
using Microsoft.Extensions.Logging;
6+
using Microsoft.Extensions.Options;
7+
8+
using SuperSocket.SocketBase.Logging;
9+
using SuperSocket.SocketBase;
10+
using SuperSocket.SocketBase.Protocol;
11+
using SuperSocket.SocketBase.Config;
12+
using System.Threading.Tasks;
13+
using System.Threading;
14+
15+
namespace PvPGameServer
16+
{
17+
public class MainServer : AppServer<NetworkSession, EFBinaryRequestInfo>, IHostedService
18+
{
19+
public static SuperSocket.SocketBase.Logging.ILog MainLogger;
20+
21+
Dictionary<int, Action<NetworkSession, EFBinaryRequestInfo>> HandlerMap = new Dictionary<int, Action<NetworkSession, EFBinaryRequestInfo>>();
22+
23+
PacketProcessor MainPacketProcessor = new PacketProcessor();
24+
RoomManager RoomMgr = new RoomManager();
25+
26+
ServerOption ServerOpt;
27+
IServerConfig m_Config;
28+
29+
private readonly IHostApplicationLifetime AppLifetime;
30+
private readonly ILogger<MainServer> AppLogger;
31+
32+
33+
34+
public MainServer(IHostApplicationLifetime appLifetime, IOptions<ServerOption> serverConfig, ILogger<MainServer> logger)
35+
: base(new DefaultReceiveFilterFactory<ReceiveFilter, EFBinaryRequestInfo>())
36+
{
37+
ServerOpt = serverConfig.Value;
38+
AppLogger = logger;
39+
AppLifetime = appLifetime;
40+
41+
NewSessionConnected += new SessionHandler<NetworkSession>(OnConnected);
42+
SessionClosed += new SessionHandler<NetworkSession, CloseReason>(OnClosed);
43+
NewRequestReceived += new RequestHandler<NetworkSession, EFBinaryRequestInfo>(OnPacketReceived);
44+
}
45+
46+
public Task StartAsync(CancellationToken cancellationToken)
47+
{
48+
AppLifetime.ApplicationStarted.Register(AppOnStarted);
49+
AppLifetime.ApplicationStopped.Register(AppOnStopped);
50+
51+
return Task.CompletedTask;
52+
}
53+
54+
public Task StopAsync(CancellationToken cancellationToken)
55+
{
56+
return Task.CompletedTask;
57+
}
58+
59+
private void AppOnStarted()
60+
{
61+
AppLogger.LogInformation("OnStarted");
62+
63+
InitConfig(ServerOpt);
64+
65+
CreateServer(ServerOpt);
66+
67+
var IsResult = base.Start();
68+
69+
if (IsResult)
70+
{
71+
AppLogger.LogInformation("서버 네트워크 시작");
72+
}
73+
else
74+
{
75+
AppLogger.LogError("서버 네트워크 시작 실패");
76+
return;
77+
}
78+
}
79+
80+
private void AppOnStopped()
81+
{
82+
MainLogger.Info("OnStopped - begin");
83+
84+
base.Stop();
85+
86+
MainPacketProcessor.Destory();
87+
88+
MainLogger.Info("OnStopped - end");
89+
}
90+
91+
public void InitConfig(ServerOption option)
92+
{
93+
m_Config = new ServerConfig
94+
{
95+
Port = option.Port,
96+
Ip = "Any",
97+
MaxConnectionNumber = option.MaxConnectionNumber,
98+
Mode = SocketMode.Tcp,
99+
Name = option.Name
100+
};
101+
}
102+
103+
public void CreateServer(ServerOption serverOpt)
104+
{
105+
try
106+
{
107+
bool bResult = Setup(new RootConfig(), m_Config, logFactory: new NLogLogFactory());
108+
109+
if (bResult == false)
110+
{
111+
MainLogger.Error("[ERROR] 서버 네트워크 설정 실패 ㅠㅠ");
112+
return;
113+
}
114+
else
115+
{
116+
MainLogger = base.Logger;
117+
}
118+
119+
CreateComponent(serverOpt);
120+
121+
MainLogger.Info("서버 생성 성공");
122+
}
123+
catch(Exception ex)
124+
{
125+
MainLogger.Error($"[ERROR] 서버 생성 실패: {ex.ToString()}");
126+
}
127+
}
128+
129+
public bool IsRunning(ServerState eCurState)
130+
{
131+
if (eCurState == ServerState.Running)
132+
{
133+
return true;
134+
}
135+
136+
return false;
137+
}
138+
139+
public void StopServer()
140+
{
141+
Stop();
142+
143+
MainPacketProcessor.Destory();
144+
}
145+
146+
public ERROR_CODE CreateComponent(ServerOption serverOpt)
147+
{
148+
Room.NetSendFunc = this.SendData;
149+
RoomMgr.CreateRooms(serverOpt);
150+
151+
MainPacketProcessor = new PacketProcessor();
152+
MainPacketProcessor.NetSendFunc = this.SendData;
153+
MainPacketProcessor.DistributePacket = this.Distribute;
154+
MainPacketProcessor.CreateAndStart(RoomMgr.GetRoomsList(), serverOpt);
155+
156+
MainLogger.Info("CreateComponent - Success");
157+
return ERROR_CODE.NONE;
158+
}
159+
160+
public bool SendData(string sessionID, byte[] sendData)
161+
{
162+
var session = GetSessionByID(sessionID);
163+
164+
try
165+
{
166+
if (session == null)
167+
{
168+
return false;
169+
}
170+
171+
session.Send(sendData, 0, sendData.Length);
172+
}
173+
catch (Exception ex)
174+
{
175+
// TimeoutException 예외가 발생할 수 있다
176+
MainLogger.Error($"{ex.ToString()}, {ex.StackTrace}");
177+
178+
session.SendEndWhenSendingTimeOut();
179+
session.Close();
180+
}
181+
return true;
182+
}
183+
184+
public void Distribute(EFBinaryRequestInfo requestPacket)
185+
{
186+
MainPacketProcessor.InsertPacket(requestPacket);
187+
}
188+
189+
void OnConnected(NetworkSession session)
190+
{
191+
// 옵션의 최대 연결 수를 넘으면 SuperSocket이 바로 접속을 짤라버린다. 즉 이 OnConneted 함수가 호출되지 않는다
192+
MainLogger.Info(string.Format("세션 번호 {0} 접속", session.SessionID));
193+
194+
var packet = ServerPacketData.MakeNTFInConnectOrDisConnectClientPacket(true, session.SessionID);
195+
Distribute(packet);
196+
}
197+
198+
void OnClosed(NetworkSession session, CloseReason reason)
199+
{
200+
MainLogger.Info(string.Format("세션 번호 {0} 접속해제: {1}", session.SessionID, reason.ToString()));
201+
202+
var packet = ServerPacketData.MakeNTFInConnectOrDisConnectClientPacket(false, session.SessionID);
203+
Distribute(packet);
204+
}
205+
206+
void OnPacketReceived(NetworkSession session, EFBinaryRequestInfo reqInfo)
207+
{
208+
MainLogger.Debug(string.Format("세션 번호 {0} 받은 데이터 크기: {1}, ThreadId: {2}", session.SessionID, reqInfo.Body.Length, System.Threading.Thread.CurrentThread.ManagedThreadId));
209+
210+
reqInfo.SessionID = session.SessionID;
211+
Distribute(reqInfo);
212+
213+
214+
215+
//_logger.LogInformation($"세션 번호 {session.SessionID}, 받은 데이터 크기: {reqInfo.Body.Length}");
216+
217+
var PacketID = reqInfo.PacketID;
218+
219+
if (HandlerMap.ContainsKey(PacketID))
220+
{
221+
HandlerMap[PacketID](session, reqInfo);
222+
}
223+
else
224+
{
225+
AppLogger.LogInformation($"세션 번호 {session.SessionID}, 받은 데이터 크기: {reqInfo.Body.Length}");
226+
}
227+
}
228+
}
229+
230+
231+
public class NetworkSession : AppSession<NetworkSession, EFBinaryRequestInfo>
232+
{
233+
}
234+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
5+
<!--
6+
See https://github.com/nlog/nlog/wiki/Configuration-file
7+
for information on customizing logging rules and outputs.
8+
-->
9+
<targets async="true">
10+
<target name="console" xsi:type="ColoredConsole" layout="${date:format=HH\:mm\:ss}| [TID:${threadid}] | ${message}" />
11+
<target name="InfoFile" xsi:type="File"
12+
fileName="${basedir}/Logs/Info_${logger}.log"
13+
archiveAboveSize="128000000"
14+
archiveFileName="${basedir}/Logs/Info_${date:format=MMddHHmm}/${shortdate}.{#####}.log"
15+
archiveNumbering="Sequence"
16+
concurrentWrites="false"
17+
layout="[${date}] [TID:${threadid}] [${stacktrace}]: ${message}" />
18+
<target name="ErrorFile" xsi:type="File"
19+
fileName="${basedir}/Logs/Error_${logger}.log"
20+
archiveAboveSize="128000000"
21+
archiveFileName="${basedir}/Logs/Error_${date:format=MMddHHmm}/${shortdate}.{#####}.log"
22+
archiveNumbering="Sequence"
23+
concurrentWrites="false"
24+
layout="[${date}] [TID:${threadid}] [${stacktrace}]: ${message}" />
25+
</targets>
26+
27+
<rules>
28+
<logger name="*" minlevel="Info" maxlevel="Info" writeTo="InfoFile" />
29+
<logger name="*" minlevel="Error" writeTo="ErrorFile" />
30+
<logger name="*" minlevel="Info" writeTo="console" />
31+
</rules>
32+
</nlog>
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
using MessagePack;
8+
9+
10+
namespace PvPGameServer
11+
{
12+
public class PKHCommon : PKHandler
13+
{
14+
public void RegistPacketHandler(Dictionary<int, Action<EFBinaryRequestInfo>> packetHandlerMap)
15+
{
16+
packetHandlerMap.Add((int)PACKETID.NTF_IN_CONNECT_CLIENT, NotifyInConnectClient);
17+
packetHandlerMap.Add((int)PACKETID.NTF_IN_DISCONNECT_CLIENT, NotifyInDisConnectClient);
18+
19+
packetHandlerMap.Add((int)PACKETID.REQ_LOGIN, RequestLogin);
20+
21+
}
22+
23+
public void NotifyInConnectClient(EFBinaryRequestInfo requestData)
24+
{
25+
}
26+
27+
public void NotifyInDisConnectClient(EFBinaryRequestInfo requestData)
28+
{
29+
var sessionID = requestData.SessionID;
30+
var user = UserMgr.GetUser(sessionID);
31+
32+
if (user != null)
33+
{
34+
var roomNum = user.RoomNumber;
35+
36+
if (roomNum != PacketDef.INVALID_ROOM_NUMBER)
37+
{
38+
var packet = new PKTInternalNtfRoomLeave()
39+
{
40+
RoomNumber = roomNum,
41+
UserID = user.ID(),
42+
};
43+
44+
var packetBodyData = MessagePackSerializer.Serialize(packet);
45+
var internalPacket = new ServerPacketData();
46+
internalPacket.Assign(sessionID, (Int16)PACKETID.NTF_IN_ROOM_LEAVE, packetBodyData);
47+
48+
DistributePacket(internalPacket);
49+
}
50+
51+
UserMgr.RemoveUser(sessionID);
52+
}
53+
}
54+
55+
56+
public void RequestLogin(EFBinaryRequestInfo packetData)
57+
{
58+
var sessionID = packetData.SessionID;
59+
MainServer.MainLogger.Debug("로그인 요청 받음");
60+
61+
try
62+
{
63+
if(UserMgr.GetUser(sessionID) != null)
64+
{
65+
ResponseLoginToClient(ERROR_CODE.LOGIN_ALREADY_WORKING, packetData.SessionID);
66+
return;
67+
}
68+
69+
var reqData = MessagePackSerializer.Deserialize< PKTReqLogin>(packetData.Data);
70+
var errorCode = UserMgr.AddUser(reqData.UserID, sessionID);
71+
if (errorCode != ERROR_CODE.NONE)
72+
{
73+
ResponseLoginToClient(errorCode, packetData.SessionID);
74+
75+
if (errorCode == ERROR_CODE.LOGIN_FULL_USER_COUNT)
76+
{
77+
NotifyMustCloseToClient(ERROR_CODE.LOGIN_FULL_USER_COUNT, packetData.SessionID);
78+
}
79+
80+
return;
81+
}
82+
83+
ResponseLoginToClient(errorCode, packetData.SessionID);
84+
85+
MainServer.MainLogger.Debug("로그인 요청 답변 보냄");
86+
87+
}
88+
catch(Exception ex)
89+
{
90+
// 패킷 해제에 의해서 로그가 남지 않도록 로그 수준을 Debug로 한다.
91+
MainServer.MainLogger.Error(ex.ToString());
92+
}
93+
}
94+
95+
public void ResponseLoginToClient(ERROR_CODE errorCode, string sessionID)
96+
{
97+
var resLogin = new PKTResLogin()
98+
{
99+
Result = (short)errorCode
100+
};
101+
102+
var bodyData = MessagePackSerializer.Serialize(resLogin);
103+
var sendData = PacketToBytes.Make(PACKETID.RES_LOGIN, bodyData);
104+
105+
NetSendFunc(sessionID, sendData);
106+
}
107+
108+
public void NotifyMustCloseToClient(ERROR_CODE errorCode, string sessionID)
109+
{
110+
var resLogin = new PKNtfMustClose()
111+
{
112+
Result = (short)errorCode
113+
};
114+
115+
var bodyData = MessagePackSerializer.Serialize(resLogin);
116+
var sendData = PacketToBytes.Make(PACKETID.NTF_MUST_CLOSE, bodyData);
117+
118+
NetSendFunc(sessionID, sendData);
119+
}
120+
121+
122+
123+
124+
}
125+
}

0 commit comments

Comments
 (0)