프로젝트 27

github action으로 CI구현

우선 이 action이 하는 일은 ChatClient와 ChatServer 프로젝트를 빌드 성공하는 것이다. 그러기 위해서 다음 단계들을 실행했다. 깃허브 레포지토리 복사하기. ServerCore.lib 을 라이브러리 디렉토리에 놓기. libprotobuf.lib 을 라이브러리 디렉토리에 놓기. Chat.sln 빌드하기. 그럼 각 단계들을 어떻게 구현했는지 알아보자. 0. 사전작업. 우선 ci.yml 파일을 만들고 몇 가지 사전작업을 했다. main 브랜치에 push 하거나 pull request를 보내면 ci.yml을 실행하도록 했다. (사실 yml파일 만드니까 기본 세팅이었다.) 아래에서 사용할 환경변수들을 설정해주었다. 빌드 모드나 다운받을 Protobuf의 버전을 명시해 놓았다. on: push:..

프로젝트/Chat 2023.02.08

ServerCore

프로젝트 소개 Github: https://github.com/jidungg/GameServer 개발 기간: 2023.1 ~ 2023.2 개발 인원 : 1명 개발 도구 및 환경 : Visual Studio 2022, C++, Windows10 설명: 실시간 채팅 서버, 클라이언트 프로그램 사용된 기술: CI(github action Google protobuf 소켓 프로그래밍(IOCP). 메모리 관리: Memory Pool, Object Pool, Stomp Allocator DataBase(MSSQL, ODBC) 주요 기능 네트워킹(서버-클라이언트 통신) 데이터베이스 멀티 스레딩 잡 큐 실행 화면 이 프로젝트는 인프런의 강의를 보고 상당 부분 참고하여 만들었습니다. https://www.inflearn..

네트워크 라이브러리

파일 목록 IocpCore.cpp/h : IocpCore 형 글로벌 변수 GIocpCore 선언. IocpEvent.cpp/h Listener.cpp/h NetAddress.cpp/h Session.cpp/h SocketUtils.cpp/h Service.copp/h 클래스 목록 IocpCore : Completion Port(이하 CP) 의 Handle(_iocpHandle)을 멤버로 가지고 있으며, 이를 관리하는 클래스. 생성자 : CreateIoCompletionPort 함수로 CP를 생성, _iocpHandle에 할당. GetHandle() : _iocpHandle을 반환 Register() : CreateIoCompletionPort 함수로 Listener 소켓과 CP를 연결해주는 함수 Disp..

STL Allocator

이 프로젝트에서 메모리 할당을 관리하기 위해 커스텀 Allocator들을 만들었다. 그런데 c++에서 기본적으로 제공하는 STL에서는 내부에서 원래 있던 new, delete를 사용할 것이다. 즉 STL을 사용하면 우리가 힘들게 만든 Allocator로 메모리를 관리할 수 없다. 따라서 우리는 STL사용 시에도 커스텀 Allocator를 사용하도록 만들 것이다. 그것이 STL Allocator이다. STL Allocator 만들기 사제 Allocator가 STL에 사용되기 위한 몇 가지 요구사항이 존재한다. tempalte를 사용할 것. using value_type 가 존재할 것. T* allocate(size_t count) 함수가 존재할 것. void deallocate(T* ptr, size_t ..

Stomp Allocator

Stomp Allocator는 기존의 new, delete의 메모리 오염 문제를 해결하기 위해 정의한 클래스이다. 메모리 오염 메모리 오염이란 메모리가 해제되었는데도 잘못 사용되는 문제를 말한다. 예를 들면 아래와 같은 상황에서 발생할 수 있다. class Knight { public: Knight() { _hp = 100; } Knight(int hp) :_hp(hp){} ~Knight() {} int _hp; }; int main() { Knight* test = new Knight(); test->_hp = 100; delete test; test->_hp = 200; //여기! } 마지막 줄에서 이미 해제된 포인터인 test의 멤버 변수 값을 수정하고 있다. 명백히 잘못된 코드이지만 이 코드는 실..

DeadLockProfiler

데드 락 방지 멀티 쓰레드에서 lock을 사용하다 보면 프로그래머의 실수로 데드 락이 발생할 수 있다. 이런 데드 락을 피하기 위해서는 프로그래머가 lock을 사용할 때 순서를 주의해서 사용해야한다. 그러나 사람은 실수를 하기 때문에 이를 보완해줄 방법이 있으면 좋을 것 같다. 데드 락을 방지하는 방법중 하나로 lock을 걸 때 현재 걸린 lock들의 상황을 파악해 이 lock이 데드락을 유발할 가능성이 있는지 검사하는 것이다. 이것이 이 프로젝트에 적용된 DeadLockProfiler 이다. 원리 데드 락은 lock 내부에서 서로의 lock이 풀릴 때까지 무한히 대기하는 현상이다. 이 서로를 기다린다는 것의 의미를 잘 생각해보자. 이 말은 lock들의 관계를 그래프로 나타내었을 때 사이클을 이루게 되면..

ReadWrite Lock

필요성 어떤 공유 데이터를 참조하는 여러 쓰레드가 있다고 가정하자. 이 쓰레드들은 평상시에는 이 공유 데이터를 읽기만 한다. 그런데 아주 드문 경우에, 예를 들면 대략 1주일에 한 번 정도 이 공유 데이터를 수정하는 일이 벌어진다고 해보자. 사실 모든 쓰레드가 읽기만 한다면 Lock을 해줄 필요가 없다. Lock이 필요한 이유는 데이터 수정이 일어났을 때 쓰레드가 잘못 된 데이터를 읽게 될 가능성이 있기 때문이다. 그런데 위의 경우에서 1주일에 한 번 있는 데이터 수정 때문에 모든 읽기 작업에도 mutex를 사용해 Lock을 걸자니 매우 비효율적이라는 생각이 든다. 이런 경우 ReadWriteLock을 사용한다. 사용방식 ReadWriteLock은 ReadLock과 WriteLock으로 나누어진다. Re..