Server programming

00_03_OT_환경 설정

devRiripong 2023. 3. 12.
반응형

요약

1. 프로젝트 만들기

  - GameServer (콘솔 앱)

  - DummyClient (콘솔 앱) - 클라 용도로 사용할

  - ServerCore (정적 라이브러리) - 서버의 핵심 네트워크 및 스렐드 기능 등등을 모아 놓은 라이브러리 파일

2. 솔루션 폴더로 가서 폴더 추가

  - Binary - 실행 결과물들 모아 놓을 것

  - Libraries - lib파일 넣어둘 곳

    - Debug, Release 폴더 추가

3. 설정

  - ServerCore 속성

    - 구성, 플래폼 변경

    - 출력 디렉토리 Libraries로 

4. ServerCore 구현

  - Network, Utils 폴더 생성

  - Utils에 파일 넣기

  - 리소스, 소스, 헤더 파일 폴더 삭제

  - framework.h 코드 pch.h에 옮기고 삭제

  - ServerCore.cpp 삭제

  - Utils에 새 클래스 CorePch 생성 - pch와 달리 GameServer, DummyClient에서 참조할 파일

  - Utils에 Type.h 헤더 파일 생성 - 매크로 형식으로 사용할 애들

  - CorePch.h에 가서 Type.h 추가하고 자주 활용할 것들 추가

  - 라이브러리 테스트 위해 CorePch에 HelloWorld() 함수 추가

  - pch.h에 CorePch.h 추가

  - Debug 설정 64비트로

5. GameServer 구현

  - Main, Utils 폴더 생성

  - Main에 파일 옮기고 리소스, 소스, 헤더 파일 폴더 삭제

  - Utils 폴더에 pch 클래스 생성, ServerCore의 pch 내용 복붙

  - pch 활용 준비 - 속성에서 C/C++ -> 미리 컴파일 된 헤더 사용, 컴파일 된 헤더 pch.h로 수정

  - pch.cpp 속성에서 미리 컴파일된 헤더 만들기로 수정

  - GameServer.cpp 에 pch.h와 CorePch.h추가

  - 라이브러리 참조 준비 - GemaServer 속성에 가서 VC++ 디렉터리에서 포함 디렉털, 추가 라이브러리 디렉터리 지정

  - 활용할 라이브러리 지정 - 링커/입력 추가 종속성에서 하거나 pch.h에 입력해주기

6. DummyClient 구현

  - 위와 같은 방법으로 하면 됨

7. GameServer, DummyClient 출력 폴더 지정

  - 프로젝트 속성 일반 -> 출력 디렉토리에서 만들어줬던 Binary 폴더로 지정

 

 

 
1. 새 프로젝트 만들기
 
프로젝트를 3개 만든다.
  1. GameServer (콘솔 앱)
  2. DummyClient (콘솔 앱)- 클라 용도로 사용할
  3. ServerCore (정적 라이브러리) - 서버의 핵심 네트워크 및 스렐드 기능 등등을 모아 놓은 라이브러리 파일
 
DummyClient 는 콘솔 앱으로,
ServerCore는 라이브러리로 만들어 줄 것이라 정적 라이브러리로 만들어 준다.
  라이브러리 만들 때 DLL로 만들 때가 있고 lib 파일로 만드는 경우가 있는데
  정적 라이브러리의 장점은 빌드를 할 때 바이너리에 해당 라이브러리의 내용이 포함 되어서 나간다. 그렇기 때문에 실행 파일이 만들어지게 되면 그 다음에는 정적 라이브러리를 일일이 같이 딸려서 관리를 할 필요가 없다.
  만약 DLL로 만들게 될 경우에는 바이너리 자체에 이 라이브러리 내용이 붙어서 같이 만들어지는게 아니기 때문에 최종 빌드를 배포해가지고 최종 실행 결과물을 만든다 해도 이 DLL을 같이 옮겨 다니면서 들고 다녀야 한다.
  실행 파일이랑 DLL을 같이 관리를 해야 하다는 얘기니 귀찮으니까 보통은 정적 라이브러리로 만드는 게 조금 더 편리하다.
 
 
2. 파일 구조 정리
 
아무 프로젝트 우클릭해서 탐색기로 가서 프로젝트 살펴 보면
솔루션 구조 이렇게 되어 있다.
여기다 새 폴더 Binary를 만든다. 실행 결과물들을 다 여기에 모아 놓도록 할 것이다.
나중에 GameServer 뿐만 아니라 LoginServer 등등 많은 서버가 추가 되는데 가기 다르게 실행파일들이 있으면 헷갈리니 모아 줄거야.
 
다시 새 폴더 Libraries를 만든다. 말 그대로 Libarary 들을 집어 넣는 폴더
오늘 만들어준 ServerCore도 결국 이 Libary로 활용이 되는 거. 물론 이걸 외부로 공개해서 게임 서버를 파는 용도는 아니지만 그럼에도 라이브러리를 만들어 주는 이유는 나중에 가면 xnl 이라거나 다양한 용도로 외부에서 만들어진 기능들을 사용하고 싶은 경우가  생길 수 있기 때문에 라이브러리들을 다 Libraries 폴더에 모아줄거야.
Libraries 폴더 안에 Debug, Release 폴더도 만들어줘서 debug 용도로 활용하는 라이브러릴랑 Release 용도로 활용하는 라이브러리 두가지로 구분을 해놓도록 할거야.
이건 필수적이진 않지만 왜 이렇게 하냐면 간혹가다 Debug 모드로 ServerCore를 빌드해서 라이브러리가 Debug 모드로 만들어졌는데 GameServer는 Release로 만들어 주게 되면 이 버전이 꼬이는 문제 종종 발생해서 분리를 해준 거.
 
3. 설정
ServerCore 프로젝트에서 우클릭->속성으로 가서
 
구성은 모든 구성, 플랫폼도 모든 플랫폼으로 변경해준다.
 
출력 디렉토리->편집
SolutionDir는 각각 환경에 맞게 변화 됨. 여기서 SolutionDir는 C:\Riripong\CPP_Server\Server로 변환이 되고
Configuration은 Debug나 Release 모드냐를 의미
아까 우리가 만들어준 경로는
이 경로에 넣어달라고 해주면 된다.
 
테스트 삼아서 ServerCore를 빌드르 해주자. 그리고 탐색기에서 폴더 열기를 해서 보면
lib 파일이 생성되어 있는 것을 볼 수 있다.
ServerCore.lib 이 파일을 읽어서 다른 프로젝트에서도 ServerCore에 넣어 놓은 기능을 공용으로 활용할 수 있다.
예를 들어 핵심 네트워크 기능이나 서버 엔진에 해당하는 부분을 다 ServerCore부분에 넣어 놓은 다음에 나중에 GameServer건 DummyClient건 다른 기타 서버 등등에서도 다 이 ServerCore를 참조하는 형태로 일단은 만들어 주면 된다.
 
4. ServerCore 구현
그리고 폴더를 더 정리해 준다.
ServerCore 프로젝트에서 리소스 파일 폴더를 삭제하고,
그리고 소스 파일, 헤더 파일을 나눠 놓을 이유가 없기 때문에 정리를 해준다.
일단 새 필터 Network, Utils를 만들어 준다.
그리고 파일들을 Utils에 다 밀어 넣어주고, 소스파일, 헤더파일 폴더는 삭제해준다.
그리고 framework.h는 별 다른 일을 하는 건 아니고
#define WIN32_LEAN_AND_MEAN            // 거의 사용되지 않는 내용을 Windows 헤더에서 제외합니다.
이 한 줄만 있으니까
pch.h의 #include "framework.h"에 복붙을 해준다.
그리고 framework.h를 삭제한다.
 
ServerCore.cpp 파일도 필요 없으니 삭제.
 
Utils에서 우클릭을 해서 새 클래스를 만들어 준다.
새 클래스 이름은 CorePch라고 한다.
Pch라는게 PreCompiledHeader라는 의미이고
여기 ServerCore에서 활용하는 모든 파일에서 공용으로 참조할 그런 애들을 다 여기 pch에 밀어 넣어 주는 것인데
CorePch 얘를 굳이 따로 파준 이유는 pch라는 애 자체는 GameServer랑 DummyClient에서 참조할 수 있는 파일이 아니다. 말 그대로 ServerCore 내부에서만 활용하는 것이기 땜문에 실질적으로 GameServer나 DummyClient 에서도 참조하길 원하는 그런 애들을 이 CorePch에다가 따로 분류를 해가지고 넣어 놓도록 할거야.
그다음에 다시 Utils에 추가->새 항목에 가서 Types.h라는 헤더 파일을 만들어 준다.
Types에 들어갈 애들은 매크로 형식으로 치환해서 사용할 애들을 만들어줄 것인데
 
using BYTE = unsigned char;
using int8 = __int8;
using int16 = __int16;
using int32 = __int32;
using int64 = __int64;
using uint8 = unsigned __int8;
using uint16 = unsigned __int16;
using uint32 = unsigned __int32;
using uint64 = unsigned __int64;
이걸 넣어준다.
__int64나 longlong 이런 식으로 타이핑하는 것이 귀찮기 때문에 이렇게 using으로 치환을 해서 사용하면 편리하다.
앞으로 생으로 int이렇게 활용안하고 int64나 int32 이런 식으로 쓸거야.
 
다시 CorePch.h에 가서
#include "Types.h" 를 추가해주고
자주 활용할 애들을 추가해 준다.
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
 
#include <iostream>
using namespace std;
 
그리고 라이브러리를 테스트하기 위해
void HelloWorld(); 를 만들어 놓는다.
CorePch.cpp에 돌아가서
 
void HelloWorld()
{
cout << "Hello Server!" << endl;
}
 
싱거운 함수를 만들어 준다.
 
 
이제 Pch.h에서 얘가 해야 할 것은
#include "CorePch.h"
해주면 된다.
 
#ifndef PCH_H
#define PCH_H
 
#endif
이걸로 하나
#pragma once로 하나 마찬가지 이므로 ifndef을 날려주고
#pragma once를 위에 써준다.
 
 
서버 같은 경우에는 32비트로 실행할 이유가 없기 때문에 Debug 부분을 x64 즉 64비트 환경으로 바꿔준다.
이렇게 하면 더 넓은 메모리 공간을 활용할 수 있기 때문이다.
그리고 ServerCore를 빌드해준다.
 
 
이제 GameServer랑 DummyClient 쪽에서 만들어준 기능들을 활용하고 싶어.
 
5. GameServer 구현
 
GameServer는 콘솔로 만들었는데 만들어질 때 precompiled header 가 기본적으로 안 만들어졌다는 걸 알 수 있어.
그래서 GameServer에 새 필터를 추가해주고 이름은 Main이라고 한다.
그리고 Utils라는 필터를 하나 더 만들어준다.
GameServer.cpp를 Main 폴더에 옮기고,
리소스 파일, 소스 파일, 헤더 파일 폴더를 삭제한다.
 
Utils폴더에 precompiled header를 추가 해줄 것인데
pch라는 이름으로 새클래스를 추가해 준다.
얘도 마찬가지로 GameServer 프로젝트에서 자주 활용되는 그런 헤더들을 pch에 넣어 놓으면 걔가 빌드가 한번에 되어서 미리 빌드를 한 다음에 나머지 애들이 활용을 할 때 재차 빌드를 할 필요 없이 빠르게 사용할 수 있는 장점이 있다.
단점은 여기 precompiled header의 내용이 수정이 되면 굉장히 많은 부분에 영향을 주는 단점이 있다. 그래도 이렇게 하는게 더 빠르기 때문에 precompiled header를 활용을 할 거야.
ServerCore에서 활용하던 내용을  pch.h에 복붙하면된다.
하지만 #include "CorePch.h"를 인지하지 못하고 빨간줄이 뜬다. 왜냐하면 CorePch.h 파일 자체가 ServerCore 프로젝트 안에 있는 것이기 때문에 얘는 그냥 곧이 곧대로 include를 해줄 수가 없다. 이거는 이따가 수정을 해주도록 하고
pch도 곧이 곧대로 동작을 하는게 아니다. pch클래스를 추가했다고 미리 컴파일 된 헤더로 동작하는게 아니라 설정을 해줘야 한다.
 
GameServer프로젝트를 우클릭해서 속성으로 간 다음에
구성 속성 -> C/C++ -> 미리 컴파일된 헤더
미리 컴파일된 헤더 사용안함을 사용으로 바꿔주면 된다.
그리고 컴파일된 헤더 자체를 stdafx.h로 한게 아니라 pch.h로 하기로 했으니까 바꿔주면 된다.
적용을 눌러주면 된다.
 
그 다음에 pch.cpp에 가서 우클릭 -> 속성으로 가서
미리 컴파일된 헤더를 사용이 아니라 만들기로 해주고 적용, 확인을 눌러준다.
이제 pch를 활용할 준비를 끝냈다.
 
 
이제 GameServer.cpp 에서도 미리 만들어준 파일들을 추가를 해주면 된다.
#include "pch.h"
그리고 오늘 하고 싶은 건
#include "CorePch.h"
이런식으로 CorePch를 긁어 와서
Main에서 HelloWorld(); 를 출력하고 싶은게 목표다.
지금은 라이브러리를 참조하고 있지 않기 때문에 얘가 당연히 실행되지 않고 있다.
 
GameServer 우클릭->속성에 가서
하는 방법이 여러가지가 있다.
구성 속성 -> C/C++ -> 일반에 가서 "추가 포함 디렉터리"를 추가를 해 준 다음에
링커->일반에 가서 여기서도 "추가 라이브러리 디렉터리"를 설정하고 이렇게 하는 방법이 하나 있고,
그게 아니면
구성 속성 -> VC++ 디렉터리 에서 "포함 디렉터리", "라이브러리 디렉터리" 여기다가 세팅을 해주는 방법이 있다. 이게 더 간단하니까 여기다 설정을 해줄거야.
즉 우리가 참조할 라이브러리는 어디에 있고, 참조할 라이브러리가 참조하는 헤더파일들 즉 ServerCore/Utils의 헤더파일들은 어느 경로에 있는지를 알려줘야 된다고 보면 된다.
 
포함 디렉터리에서 편집을 눌러 보면
기본 경로가 되어 있는데 이 아이들은 비주얼 스튜디오를 깔 때 설치된 경로들을 포함하고 있는데
오늘 추가할 애는 아직 안 들어가 있기 때문에 새로운 애들 타이핑 해주면 된다.
$(SolutionDir)ServerCore\를 타이핑 하면
아래에 C:\Riripong\CPP_Server\Server\ServerCore\ 이게 추가가 된다.
ServerCore 안에 헤더 파일들이 있기 때문에 얘를 이렇게 집어 넣어 줘야 하고
확인을 눌러주면 된다.
이제 라이브러리는 어디있냐는 것도 세팅을 해줘야 하는데
라이브러리 디렉터리 부분을 화살표를 누르고 편집을 눌러 똑같이 세팅을 해주면 된다.
$(SolutionDir)Libraries\ 라고 치면
아래에 C:\Riripong\CPP_Server\Server\Libraries\ 가 추가된다.
Libraries 안에 있으니까 여기서 상대경로로 찾으면 된다고 알려주고 있는 거.  확인을 누르고 적용을 눌러주면 된다.
이렇게 실질적으로 어디서 찾아야 될지를 알려준 다음에
 
 
여기서도 방법이 갈리는데
링커->입력으로 가서 추가 종속성을 보면 활용하고 있는 라이브러리들이 있다.
여기다가 추가할 ServerCore.lib를 여기다가 입력을 해도 되고
근데 여기서 매번 하는 건 귀찮으니까 pch.h에다가 넣어주는 방법이 있다.
 
디버그 상태이냐에 따라 해당 라이브러리를 입력을 해주겠다 라는 걸 해줄건데
#ifdef _DEBUG
#pragma comment(lib, "Debug\\ServerCore.lib")
#else
#pragma comment(lib, "Release\\ServerCore.lib")
#endif
이렇게 해주면 우클릭 속성에 가서 경로를 일일이 입력할 필요 없이 이건 전처리기 단계에서 실행이 되기 때문에 미리 ServerCore.lib를 긁어 오게 될거야.
 
이렇게 해서 빌드를 해본다.
통과하는 걸 알 수 있고 ctrl+f5를 눌러보면
Hello Server! 가 뜨는 걸 알 수 있다.
 
이렇게 라이브러리로 참조하고 있으면 디버깅도 똑같이 할 수 있다.
 
하나의 내용을 두개로 쪼개가지고 공용으로 사용할 프로젝트로 관리하고 있는 부분이 이렇게 들어간다고 보면된다.
 
6. DummyClient 구현
DummyClient 도 똑같이 세팅을 해줘야 한다.
Main 폴더 만들어주고, Utils 폴더 만들어 주고 DummyClient.cpp를 Main에 옮겨주고,
리소스, 소스, 헤더 파일 폴더를 삭제해 준다.
 
Utils 폴더에 pch 클래스를 생성한다.
 
DummyClient.cpp로 돌아가서
#include "pch.h"를 추가해준다.
여기서도 마찬가지로 main에서 HelloWorld();를 호출해 줄 수 있으면 된다.
ServerCore라이브러리를 긁어와서 사용할 준비가 끝났다는 의미.
 
pch.h의 내용은 GameServer와 마찬가지로 긁어와서 pch.h에 복붙해 준다.
 
#define WIN32_LEAN_AND_MEAN 
 
#ifdef _DEBUG
#pragma once comment(lib, "Debug\\ServerCore.lib")
#else
#pragma once comment(lib, "Release\\ServerCore.lib")
#endif
 
#include "CorePch.h"
 
나머지 부분은 DummyClient 우클릭을 해서 똑같이 해준다.
VC++ 디렉터리에 가서 "포함 디렉터리"와 "라이브러리 디렉터리"를 지정해준다.
 
빌드를 하고
DummyClient를 우클릭해서 시작 프로젝트로 설정을 눌러준다.
ctrl+f5를 눌러주면 Hello Server! 뜨는 걸 알 수 있다.
 
이렇게 해서 ServerEngine으로 활용할 ServerCore를 만들어줬고,
Client와 Server를 만들어 줘서 각각 컨텐츠 단을 담당하는 부분을 만들어 놓았다.
 
다음 시간부터 본격 서버와 관련된 내용을 공부한다.
Multi thread, Smart pointer, Network programminmg에 관해 알아 보면서 조금씩 내용을 발전 시켜서 쌓아 나가게 될 거야.
 
7. GameServer, DummyClient 출력 폴더 지정
 
아직 빼 먹은게
 
여기 Binary에 출력을 하길 원하는데
 
기본적으로 x64에다가 만들어 놓고 있는 걸 볼 수 있어.
x64는 일단 삭제 하고 설정을 바꿔주자.
 
DummyClient 에서 우클릭 속성에 가서
구성 속성->일반에서 출력 디렉터리를 바꿔주면 된다.
이렇게 되어 있는데
Binary에 넣어 달라고 수정을 해준다.
 
GameServer 프로젝트도 마찬가지로 해준다.
 
다시 두개의 프로젝트를 각각 빌드를 하고 탐색기에서 살펴 보면
 
Binary의 Debug 안에 들어가 있는 걸 볼 수 있다.
실질적으로 서버를 배포하게 되면 exe파일이 관건이고 얘를 들고 가서 서버 머신에서 띄우게 될거야.
pdb는 나중에 혹시라도 서버가 뻗을 때 크래시 덤프를 남기게 될건데 크래시 덤프의 심볼이랑 관련이 있다. 이건 나중에 다룰 것.
 
일단 오늘 세팅은 이렇게 마무리가 된다.
 
반응형

'Server programming' 카테고리의 다른 글

01_02_멀티쓰레드_쓰레드 생성(구버전)  (0) 2023.03.12
01_01_멀티쓰레드 개론  (0) 2023.03.12
00_02_OT_서버 개론  (0) 2023.03.12
00_01_OT_OT  (0) 2023.03.12
02_08_멀티쓰레드 프로그래밍_Sleep  (0) 2022.08.05

댓글