서버 39

1. 동기화 기법

게임 서버를 만들 때 클라이언트끼리 싱크를 맞추는 것이 중요한데 이를 위한 기법들은 어떤 것이 있는지 알아보자.1. LockStep락스텝은 매 프레임마다 모든 플레이어의 입력값을 동기화해서 클라이언트에게 전송하는 방법이다. 간단하게 어떻게 수행되는지 단계를 보자.1) 클라이언트가 자신의 명령(입력이나 행동)을 서버에 전송한다.2) 서버는 클라이언트들의 명령을 수집한 후, 모든 클라이언트에게 동시에 뿌린다.3) 클라이언트는 수신된 명령을 똑같이 처리한다. 장점1) 모든 클라이언트가 똑같은 순서로 같은 입력들을 처리하기 때문에 일관된 상태를 유지할 수 있다.2) 입력 명령만을 주고 받기 때문에 대역폭을 적게 사용하기 때문에 대역폭 관리가 수월하다. 단점1) 서버가 모든 클라이언트의 입력이 들어올 때까지 대기..

서버/동기화 2025.01.24

5. Session#2

지금까지는 RecvBuffer에 그냥 다 때려박았는데 생각해보면 처리되지 않은 데이터들을 그냥 다 버퍼에 넣어버리는 건 당연히 하면 안될 일이다.물론 아직 완성되지 않았기 때문에 그렇지만 이런 것들을 생각하면서 코드를 작성해보도록 하자.이번엔 저번 게시글에 이어 Send하는 부분을 만들어 볼 것이다. 지금 작성하는 코드는 Send의 단계를 이해하기 위한 코드이므로 이후 삭제될 코드들이 꽤 많이 들어간다. Session.h#pragma once#include "IocpCore.h"#include "IocpEvent.h"#include "NetAddress.h"class Service;//------------// Session//------------class Session : public IocpObj..

3. Service

지난번에 iocpCore를 만들어서 실행해보았고 이를 좀 더 편하게 관리하기 위해 Service라는 것을 도입했다.이에 맞춰 기존의 라이브러리를 조금 수정했다. Service.h#pragma once#include "NetAddress.h"#include "IocpCore.h"#include "Listener.h"#include enum class ServiceType : uint8{ Server, Client};//-------------// Service//-------------using SessionFactory = function;class Service : public enable_shared_from_this{public: Service(ServiceType type, NetAddress ..

8. Overlapped 모델 (이벤트 방식)

https://velog.io/@nittre/%EB%B8%94%EB%A1%9C%ED%82%B9-Vs.-%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9-%EB%8F%99%EA%B8%B0-Vs.-%EB%B9%84%EB%8F%99%EA%B8%B0 블로킹 Vs. 논블로킹, 동기 Vs. 비동기와 드디어 이해했다 속이 후련~velog.io먼저 동기 vs 비동기, 블로킹 vs 논블로킹에 대해서 확실히 알아보자.위 블로그에 잘 설명되어 있으니 참고하도록 하자. 동기, 비동기의 예시로 전화와 메일을 들 수 있다. 동기 : 전화를 통해서 질문에 대한 답을 받는 것(동시)비동기 : 메일을 통해서 답을 받는 것(보내고 신경쓰지 않음, 동시 X) 자주 사용되는 조합(?)은 (동기, 블로킹), (비동기, 논블로..

서버/네트워크 2024.10.11

2. IocpCore

본격적으로 IOCP를 구현해보자 IocpCore.h#pragma once// Iocp에 등록할 수 있는 객체//---------------// IocpObject//---------------class IocpObject{public: virtual HANDLE GetHandle() abstract; virtual void Dispatch(class IocpEvent* iocpEvent, int32 numOfByte = 0) abstract;};//-------------// IocpCore//-------------class IocpCore{public: IocpCore(); ~IocpCore(); HANDLE GetHandle() { return _iocpHandle; }; // 세션, 소켓 생..

1. Socket Utils

본격적으로 라이브러리를 쌓아올리는 과정이다. 먼저 소켓을 초기화하고 인자를 설정하는 등 소켓에 대한 내용이다. SocketUtils.h#pragma once#include "NetAddress.h"// 매핑을 해줘서 편하게 사용하기 위함//----------------// Socket Utils//----------------class SocketUtils{public: static LPFN_CONNECTEX ConnectEx; static LPFN_DISCONNECTEX DisconnectEx; static LPFN_ACCEPTEX AcceptEx;public: static void Init(); static void Clear(); static bool BindWindowsFunction(SOC..

7. WSAEventSelect 모델

이 모델에서는 Select 모델과 다르게 매번 전체 초기화를 할 필요가 없다.이벤트 객체와 소켓을 한 번 연동해주기만 하면 알아서 매핑을 해주기 때문에 잘 작동한다.#include "pch.h"#include "CorePch.h"#include #include "ThreadManager.h"#include #include #include #pragma comment(lib, "ws2_32.lib")void HandleError(const char* cause){ int32 errCode = ::WSAGetLastError(); cout 접속한 클라이언트가 있을 때 // connect -> 서버에 접속 성공했을 때 // send, sendto -> 요청한 데이터를 송신 버퍼에 복사했을 때 // recv..

서버/네트워크 2024.09.09

6. Select 모델

블로킹 소켓을 논블로킹으로 바꾼다고 다 좋은 것이 아니라는 것을 실습을 통해 알아보았다. 제대로 완료가 되지 않은 함수를 논블로킹 방식에서 그냥 리턴을 해주어서 예외처리를 해주어야 하고 그로 인해 무한루프를 돌며 CPU를 더 잡아먹는 불편함이 있었다. 그렇다면 논블로킹 모델을 사용하되 준비된 상태를 미리 파악하게 하면 어떨까하는 생각을 할 수 있는데 이가 바로 Select 모델의 컨셉이다. Server.cpp#include "pch.h"#include "CorePch.h"#include #include "ThreadManager.h"#include #include #include #pragma comment(lib, "ws2_32.lib")void HandleError(const char* cause){..

서버/네트워크 2024.09.05

5. 논블로킹(Non-Blocking) 소켓

우리가 지금까지 사용해왔던 소켓은 블로킹(Blocking) 방식 소켓이다. 우리가 통신을 하면서 사용했던 함수들이 언제 완료되는지 한 번 보자. accept -> 접속한 클라이언트가 있을 때 connect -> 서버에 접속 성공했을 때  send, sendto -> 요청한 데이터를 송신 버퍼에 복사했을 때 recv, recvfrom -> 수신 버퍼에 도착한 데이터가 있고, 이를 유저레벨 버퍼에 복사했을 때 이렇게 어떠한 행위가 끝날 때 비로소 함수가 종료된다. 함수가 실행되는 동안에는 대기를 해야한다는 뜻이다. 말그대로 블로킹(Blocking) 당하는 것이다. 게임을 한 번 생각해보자. 몇 천 명이 동시에 서버에 접속을 한다고 할 때 저렇게 대기를 하면 당연히 문제가 생길 수 밖에 없다. 그렇다고 접속을..

서버/네트워크 2024.09.03