PacketProcessor 클래스

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

using System.Threading.Tasks.Dataflow;

using CSBaseLib;

namespace ChatServer
{
    class PacketProcessor
    {
			  // 스레드 실행 여부 체크용 변수
        bool IsThreadRunning = false;
        // 처리 스레드 객체 선언
        System.Threading.Thread ProcessThread = null;

        //receive쪽에서 처리하지 않아도 Post에서 블럭킹 되지 않는다. 
        //BufferBlock<T>(DataflowBlockOptions) 에서 DataflowBlockOptions의 BoundedCapacity로 버퍼 가능 수 지정. BoundedCapacity 보다 크게 쌓이면 블럭킹 된다
        BufferBlock<ServerPacketData> MsgBuffer = new BufferBlock<ServerPacketData>();
				// 유저 매니저 선언
        UserManager UserMgr = new UserManager();
		        
		    // 방 번호 범위를 나타내는 튜플
        Tuple<int,int> RoomNumberRange = new Tuple<int, int>(-1, -1);
        List<Room> RoomList = new List<Room>();

        Dictionary<int, Action<ServerPacketData>> PacketHandlerMap = new Dictionary<int, Action<ServerPacketData>>();
        // 일반적인 패킷 처리 담당
        PKHCommon CommonPacketHandler = new PKHCommon();
        // 방 관련 패킷 처리 담당
        PKHRoom RoomPacketHandler = new PKHRoom();

CreateAndStart

//TODO MainServer를 인자로 주지말고, func을 인자로 넘겨주는 것이 좋다
public void CreateAndStart(List<Room> roomList, MainServer mainServer)
{
		// 최대 유저 수 = 최대 방 수 * 방 당 최대 유저 수
		var maxUserCount = MainServer.ServerOption.RoomMaxCount * MainServer.ServerOption.RoomMaxUserCount;
		// 최대 유저 수 초기화
		UserMgr.Init(maxUserCount);

		// 클래스 변수 RoomList에 매개변수로 받은 리스트 복사
		RoomList = roomList;
		// 첫 번째 방 번호
		var minRoomNum = RoomList[0].Number;
		// 마지막 방 번호
		var maxRoomNum = RoomList[0].Number + RoomList.Count() - 1;
		// 현재 방 번호 범위(첫번째 방 ~ 마지막 방) 튜플 생성
		RoomNumberRange = new Tuple<int, int>(minRoomNum, maxRoomNum);
            
    // 각 패킷 핸들러(일반, 방 전용)의 패킷아이디/함수포인터 딕셔너리 추가하는 함수 호출
		RegistPacketHandler(mainServer);

		// 스레드가 돌고있다고 변수 수정
		IsThreadRunning = true;
		// 스레드 할당 후 Process 메서드를 실행하도록 설정
		ProcessThread = new System.Threading.Thread(this.Process);
		// 스레드 시작
		ProcessThread.Start();
}

Destroy

public void Destory()
{
    IsThreadRunning = false;
    MsgBuffer.Complete();
}

InsertPacket

public void InsertPacket(ServerPacketData data)
{
    MsgBuffer.Post(data);
}

RegistPacketHandler

void RegistPacketHandler(MainServer serverNetwork)
{            
		CommonPacketHandler.Init(serverNetwork, UserMgr);
		CommonPacketHandler.RegistPacketHandler(PacketHandlerMap);                
            
		RoomPacketHandler.Init(serverNetwork, UserMgr);
		RoomPacketHandler.SetRooomList(RoomList);
		RoomPacketHandler.RegistPacketHandler(PacketHandlerMap);
}

Process

void Process()
{
		// 스레드가 실행중인 동안 계속 돔
		while (IsThreadRunning)
		{
        //System.Threading.Thread.Sleep(64); //테스트 용
        try
        {
		        // MsgBuffer에서 패킷 받기
            var packet = MsgBuffer.Receive();

						// 패킷의 아이디에 해당하는 값 확인
            if (PacketHandlerMap.ContainsKey(packet.PacketID))
            {
		            // 패킷 아이디에 맞는 함수 호출
                PacketHandlerMap[packet.PacketID](packet);
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("세션 번호 {0}, PacketID {1}, 받은 데이터 크기: {2}", packet.SessionID, packet.PacketID, packet.BodyData.Length);
            }
        }
        catch (Exception ex)
        {
            IsThreadRunning.IfTrue(() => MainServer.MainLogger.Error(ex.ToString()));
        }
}