Socket _listenSocket;
Action<Socket> _onAcceptHandler;
public void Init(IPEndPoint endPoint, Action<Socket> onAcceptHandler)
{
_listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_onAcceptHandler += onAcceptHandler;
// 문지기 교육
_listenSocket.Bind(endPoint);
// 영업시작
// backlog : 최대 대기수
_listenSocket.Listen(10);
// AcceptAsync에 필요한 것
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
// Accept가 완료되면 실행할 이벤트
args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted);
RegisterAccept(args);
}
args.Completed는 Accept가 완료되면 실행할 이벤트를 설정하는 핸들러이다.
void RegisterAccept(SocketAsyncEventArgs args)
{
args.AcceptSocket = null;
bool pending = _listenSocket.AcceptAsync(args);
if (pending == false)
OnAcceptCompleted(null, args);
}
Init함수에서 실행될 함수이다.
_listen소켓을 비동기 방식으로 Accept한다.
이후 클라에서 Connect가 되면 OnAccpetCompleted 함수를 실행한다.
pending 변수는 Accpet 이후에 바로 Connect가 되는 경우를 처리하기 위해 사용하였다.
void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
{
if (args.SocketError == SocketError.Success)
{
// 생성된 소켓을 매개변수로 사용
_onAcceptHandler.Invoke(args.AcceptSocket);
}
else
Console.WriteLine(args.SocketError.ToString());
// Accept되면 다시 Register한다.
RegisterAccept(args);
}
이벤트 핸들러는 매개변수로 sender, args가 필요하기에 넣어주었다.
Accept가 완료되면 _onAcceptHandler에 연결된 함수를 실행한다.
이후 다시 Accept 등록을 실시한다.
namespace SeverCore
{
internal class Program
{
static Listener _listener = new Listener();
static void OnAcceptHandler(Socket clientSocket)
{
try
{
// 받는다
byte[] recvBuff = new byte[1024];
int recvBytes = clientSocket.Receive(recvBuff);
string recvData = Encoding.UTF8.GetString(recvBuff, 0, recvBytes);
Console.WriteLine($"[From Client] {recvData}");
// 보낸다
byte[] sendBuff = Encoding.UTF8.GetBytes("Welcome to MMORPG Server!");
clientSocket.Send(sendBuff);
// 쫓아낸다
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
Listener에서 사용할 이벤트 함수이다.
생성된 소켓을 사용하여 데이터를 주고받는 부분을 이쪽에 넣었다.
static void Main(string[] args)
{
// DNS (Domain Name System)
string host = Dns.GetHostName();
IPHostEntry ipHost = Dns.GetHostEntry(host);
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777);
_listener.Init(endPoint, OnAcceptHandler);
Console.WriteLine("Listening...");
while (true)
{
}
}
Init함수를 실시하여 비동기적으로 Accept를 실시한다.
잘 작동함을 확인하였다.