C#으로 게임서버 만들기

네트워크 API로 만들수도 있지만, 그보다는 이미 만들어져있는 오픈소스 라이브러리를 사용해서 게임서버 만드는걸 추천

오픈소스를 쓰면 개발기간 단축, 여러사람이 사용해서 신뢰성이 있어서 안정적이고 빠르게 개발 가능

SuperSocketLite는 SuperSocket을 개량한 것


MainServer.cs

MainServer 클래스

생성자

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Runtime.CompilerServices;
using System.Diagnostics;

using SuperSocket.SocketBase.Logging;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using SuperSocket.SocketBase.Config;
using System.Threading;

namespace EchoServer
{
		// AppServer를 상속받는 MainServer 클래스 생성
		// AppServer 클래스는 TCP/IP 통신을 위한 서버를 구현하는데 사용
		// AppServer<서버가 처리하는 세션의 형식, 서버가 처리하는 요청의 형식>
		// NetworkSession은 클라이언트와의 세션을 나타냄
		// EFBinaryRequestInfo는 이 세션에서 주고받는 이진 데이터의 형식을 정의
    class MainServer : AppServer<NetworkSession, EFBinaryRequestInfo>
    {
		    // SuperSocket 라이브러리의 로깅 인터페이스인 ILog
		    // 서버의 로그를 기록하고 관리
		    // 여러 클래스 및 메서드에서 공유하고 일관된 로그 기능 쓰기 위해서 static으로 선언
		    // MainLogger.Info("로그 메시지") 처럼 로그 기록 가능
        public static SuperSocket.SocketBase.Logging.ILog MainLogger;
               
        // 서버 설정용 객체 
        IServerConfig m_Config;

				// 서버가 현재 실행 중인지 나타내기 위한 플래그
        bool IsRun = false;
        // 클라이언트의 요청 수를 계산할 때 쓰려고 만든 스레드
        Thread CounterTh;

				// MainServer 클래스의 생성자
				// 부모 클래스인 AppServer의 생성자를 호출하고 있음
				// DefaultReceiveFilterFactory 클래스를 사용해서 수신 필터를 설정함
        public MainServer() // base = 부모의 생성자 사용, () 안에 부모의 생성자에 전달할 매개변수
            : base(new DefaultReceiveFilterFactory<ReceiveFilter, EFBinaryRequestInfo>())
		     // DefaultReceiveFilterFactory : 수신된 데이터를 처리하는 필터를 생성하는 팩토리 SuperSocket 서버에서 데이터를 수신하고 처리하기 전에 필요한 필터를 생성함
		     // <> 안은 이 필터팩토리를 만들 때 사용할 두 가지 형식 지정 제네릭
		     // ReceiveFilter : 서버가 클라로부터 받은 데이터를 이해하고 처리하는 방법 정의
		     // EFBinaryRequestInfo : 수신된 데이터의 구조를 파악하고 필요한 정보를 추출하는데 사용된다
		     // 이 팩토리를 쓰면 서버는 데이터를 수신하고 처리하기 위해 필요한 기본 수신 필터를 생성할 수 있음 -> 이 필터로 수신된 데이터 해석하고 클라이언트 요청 인식
        {
		        // 클라이언트의 연결, 연결 종료, 요청 수신 이벤트 핸들러 등록
		        
						// 새로운 세션이 연결되면 OnConnected를 호출하도록 핸들러 등록
						// 세션의 형식은 NetworkSession
            NewSessionConnected += new SessionHandler<NetworkSession>(OnConnected);

						// 세션이 종료되면 = 클라가 연결을 끊으면 OnClosed를 호출하도록 핸들러 등록
						// 세션의 형식은 NetworkSession, 이벤트 종료 원인은 CloseReason 형식
            SessionClosed += new SessionHandler<NetworkSession, CloseReason>(OnClosed);
 
						// 클라이언트로부터 새로운 요청을 받으면 RequestReceived 호출하도록 핸들러 등록
						// 세션의 형식은 NetworkSession, 클라이언트로부터 수신한 이진 형식의 요청 데이터는 EFBinaryRequestInfo
            NewRequestReceived += new RequestHandler<NetworkSession, EFBinaryRequestInfo>(RequestReceived);
        }

RegistHandler

void RegistHandler()
{
    //HandlerMap.Add((int)PACKETID.REQ_ECHO, CommonHan.RequestEcho);

    MainLogger.Info("핸들러 등록 완료");
}

InitConfig

// 서버 설정을 초기화하는 메서드
// ServerOption을 매개변수로 받아서 서버의 포트번호, 최대 연결수 등을 설정
public void InitConfig(ServerOption option)
{
		// 서버 구성을 위한 ServerConfig 객체를 만들고 그 안에 매개변수로 받은 option 사용해서 설정
    m_Config = new ServerConfig
    {
        Port = option.Port, // 포트번호
        Ip = "Any", // IP 주소는 모든 네트워크 인터페이스
        MaxConnectionNumber = option.MaxConnectionNumber, // 최대 연결 수
        Mode = SocketMode.Tcp, // 소켓 모드 TCP
        Name = option.Name // 서버 이름
    };
}