C# Rookiss Part4 ๊ฒ์์๋ฒ : Session
๐โโ๏ธSession
์ธ์ ์ข ํฉ๋ณธ.
๐ชSession
namespace ServerCore
{
abstract class Session
{
Socket _socket;
int _disconnected = 0;
object _lock = new object();
Queue<byte[]> _sendQueue = new Queue<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 void OnRecv(ArraySegment<byte> buffer);
public abstract void OnSend(int numOfBytes);
public abstract void OnDisconnected(EndPoint endPoint);
public void Start(Socket socket)
{
_socket = socket;
_recvArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnRecvCompleted);
_recvArgs.SetBuffer(new byte[1024], 0, 1024);
_sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);
RegisterRecv();
}
public void Send(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();
}
#region ๋คํธ์ํฌ ํต์
void RegisterSend()
{
_pendingList.Clear();
while (_sendQueue.Count > 0)
{
byte[] buff = _sendQueue.Dequeue();
_pendingList.Add(new ArraySegment<byte>(buff, 0, buff.Length));
}
_sendArgs.BufferList = _pendingList;
bool pending = _socket.SendAsync(_sendArgs);
if (pending == false)
OnSendCompleted(null, _sendArgs);
}
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)
{
Console.WriteLine($"OnSendCompleted Failed {e}");
}
}
else
{
// TODO DIsconnect
Disconnect();
}
}
}
void RegisterRecv()
{
bool pending = _socket.ReceiveAsync(_recvArgs);
if (pending == false)
OnRecvCompleted(null, _recvArgs);
}
void OnRecvCompleted(object sender, SocketAsyncEventArgs args)
{
if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success)
{
try
{
OnRecv(new ArraySegment<byte>(args.Buffer, args.Offset, args.BytesTransferred));
RegisterRecv();
}
catch (Exception e)
{
Console.WriteLine($"OnRecvCompleted Failed {e}");
}
}
else
{
Disconnect();
}
}
#endregion
}
}
๐ช๋ถ์
-
Session1 - Recv
-
SocketAsyncEventArgs๋ ๋ ๋ฆฝ์ ์ด์ฌ์ ์ฌ๋ฌ๊ฐ๋ฅผ ๋ง๋ค๋ฉด ๊ฐ์๊ฐ ์ผ์ ํจ - ์ฐ๋ ๋์ฒ๋ผ ์๊ฐํ๋ฉด ๋ ๋ฏ
-
Async๊ณ์ด์ ํจ์๋ฅผ ๋ง๋ค๊ณ AsyncEventArgs๋ฅผ ๋ฃ์ด ์ค ๊ฒฝ์ฐ ์ฝ๋ฐฑํจ์๋ ๋ณ๋์ ์ฐ๋ ๋๋ฅผ ๋ง๋ ๋ค
-
Session์ผ๋ก ๋ง๋ ๋ถ๋ถ์ Receive, Send, Disconnect
-
-
Session2 - Send
-
Send๋ ๊ทธ ์์ ์ RegisterSend๋ฅผ ํ๊ฒ ๋ง๋ค์ด์ค - SocketAsyncEvent๋ฅผ ์๋ก ๋ง๋ค์ด ์ฃผ๊ณ SetBuffer๋ฅผ ํ ํ RegitserSend
-
=> ์ฌ์ฌ์ฉ ํ ์ ์์, ๋ถํ๊ฐ ํผ(๋คํธ์ํฌ ์ก์์ ๋ถ๋ถ์ด ๋ถํ๊ฐ ํผ), ์ ์ ๋ชจ๋์์ ๋คํธ์ํฌ ํจํท์ ๋ณด๋ด๋ ๊ฒ์ ๋ณดํต ๋ถ๊ฐ๋ฅํ๊ณ ์ด๋ฐ๊ฒ๋ค์ ์ด์์ฒด์ ๊ฐ ์ปค๋๋จ์์ ํจ
-
=> SocketAsyncEventArgs๋ฅผ ์ฌ์ฌ์ฉํ๊ณ ์ถ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ญ์ณ์ ๋ณด๋ด๊ณ ์ถ๋ค!! ( SocketAsyncEventArgs )๋ฅผ ๋ฐ์ผ๋ก ๋นผ์
-
Queue๋ฅผ ๋ง๋ค์ด์ ์ฐจ๊ณก์ฐจ๊ณก ์์์ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌ ๋๊ฒ ๋ง๋ค๊ธฐ ( OnSendCompleted๊ฐ ๋๋๊ธฐ ์ ๊น์ง ๋ณด๋ด์ง ์๊ณ Queue์ ์๊ธฐ)
-
Send๋ ์ธ์ ์ฌ์ฉ๋ ์ง ์์ธก ํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ ๋งด๋ฒ๋ณ์๋ก _sendArgs๋ฅผ ๋ง๋ค๊ณ ์ค์ ์ฌ์ฉ๋ ๋ Register์์์ _sendArgs๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์, ๋ณด๋ด๋ ์์ ์ด ์๋ฃ ๋์ง ์์ ๋ ๋๊ตฐ๊ฐ๊ฐ ๋ณด๋ด๋ ์์ ์ ํ๋ค๋ฉด ์ผ๋จ Queue์ ์์๋์๋ค๊ฐ ๋์ค์ ์ฒ๋ฆฌ
-
-
Session3 - BufferList
-
BufferList์ SetBuffer๋ ๋์์ ์ฌ์ฉ ๋ชปํจ
-
ArraySegment : ์ด๋ค Array์ ์ผ๋ถ๋ฅผ ๋ฐํํ๋ ๊ตฌ์กฐ์ฒด - ํ์ด ์๋๋ผ ์คํ์ ํ ๋น๋จ
-
cs์ cpp์ ๋ฌ๋ฆฌ ํฌ์ธํฐ์ ๊ฐ๋ ์ด ์๊ธฐ ๋๋ฌธ์ ์ฃผ์๋ฅผ ๋๊ธฐ๋๊ฒ ์๋๋ผ ์ธ๋ฑ์ค๋ฅผ ๋๊ธฐ๊ณ ํฌ๊ธฐ๋ฅผ ์ ํจ - ex) new ArraySegment
(buff, 0, buff.Length)
-
-
Session4 - ์ถ์ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ์ด๋ฒคํธํ์์ผ๋ก ์ฝ๋ฐฑํ๊ธฐ
-
abstract ํด๋์ค๋ ๋ง๋ฐ๋ก ์ฌ์ฉ ๋ชปํจ
-
์ฝ๋ฐฑํ์์ ์ทจํ๊ธฐ ์ํด Session์ ์์๋ฐ์ GameSession์ ๋ง๋ค์ด์ ์ถ์ํด๋์ค ๊ตฌํ
-
_sessionFactory ์ธ์ ์ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋๊ตฌ๋ฅผ ๋ง๋ค์ด ์ค์ง ์ ์ํ๋ Func( out ๊ฒฐ๊ณผ๊ฐ์ด ์์ ) => ์ธ์ ์ ๋๊ตฌ๋ฅผ ๋ง๋ค์ด์ค์ง ์ ์ํ๋ฉด์ ์ฌ์ฉํด์ผ ๋จ ( _listner.Init(endPoint, () => { return new GameSession(); }
-
์ปจํ ์ธ ๋จ๊ณผ ์์ง๋จ์ ๊ตฌ๋ณํ๊ธฐ ์ํ ์์ ๋ค!
-
-> Session session = _sessionFactory.Invoke(); ์ฌ์ฉ๊ฐ๋ฅ, ์ด๋ค ์ธ์ ์ ๋ง๋ค์ง ๋ชจ๋ฅด๋๊น Session์ ๋ฑ๋ _sessionFactory๋ฅผ ๋ง๋ ๊ฒ์ด ํฌ์ธํธ
-