GameChoi
Choi Programming
GameChoi
전체 방문자
오늘
어제
  • 분류 전체보기 (468)
    • C++ Algorithm & Study (184)
      • C++ & Algorithm Strategies (45)
      • Game Math & DirectX 11 (72)
      • Server + UE5 (29)
      • Lyra Clone Coding (37)
    • Create Game (284)
      • [Window API] Game Client & .. (55)
      • [DirectX] DirectX 2D & 3D (155)
      • [UE5] BLUEPRINT & C++ (74)
    • odds and ends (0)
      • English (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • UE5
  • Game Server
  • GAME Client
  • session
  • Player Move Packet
  • Game Room
  • Direct3D
  • RPG Game
  • protobuf
  • client
  • core
  • server
  • c++
  • job queue
  • Destination Move Packet
  • Player State
  • Algorithm Strategies
  • Direct11
  • Network Worker
  • Other Character

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
GameChoi

Choi Programming

[SERVER] WSAEvent Select
Create Game/[Window API] Game Client & Game Server

[SERVER] WSAEvent Select

2023. 1. 13. 19:51

1. WSAEventSelect (Windows Socket Async)

1.1 WSAEventSelect 의미

 - 입출력 함수를 안전하게 호출할 수 있는 시점을 운영체제가 알려줌

   - 단순한 입출력 방식보다 편리하게 여러개의 소켓을 처리
 - 운영체제에서 함수 호출의 시점을 알려주기 때문에 비동기처럼 처리할 수 있음

 - 비동기 입출력 모델 (Overlapped I/O, IOCP)

1.2 Select Code 수정

https://choiprogramming.tistory.com/110

 

[SERVER] Select

1. Select 1.1 Non-blocking Socket의 문제 - 함수의 결과를 예상X - 패킷 수신 여부와 관계없이 바로 리턴 → buf의 상태가 어떤지 알 방법X - 소켓이 Read/Write 할 수 있는 상태인지 아닌지 판별해 주는 select

choiprogramming.tistory.com

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 클라이언트로 전달 받은 소켓 저장할 배열 생성

	// Close WSA
}

1.3 WSAEventSelect 

 - 이벤트 객체를 활용하여 네트워크의 이벤트 상태를 감지

   - 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성 (1 대 1 대응상태)

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성
	vector<Session> socketVector;
	vector<WSAEVENT> socketEventVector;
    
	// Close WSA
}

 - 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장

   - Listen Socket은 3번째 인자로 선택한 이벤트를 감지할 수 있음

     - 3번째 인자는 이벤트가 감지할 이벤트의 종류를 지정

       - FD (ACCPET, READ, WRITE, OOB, QOS, CLOSE)

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성
    
	// 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장
	WSAEVENT listenEvent = WSACreateEvent();
	socketVector.push_back(Session{listenSocket});
	socketEventVector.push_back(listenEvent);

	WSAEventSelect(listenSocket, listenEvent, FD_ACCEPT | FD_CLOSE);
    
	// Close WSA
}

 - 발생한 이벤트를 감시

DWORD WSAWaitForMultipleEvents(DWORD cEvents,const WSAEVENT *lphEvents,
			WINBOOL fWaitAll,DWORD dwTimeout,WINBOOL fAlertable);

   - 이벤트 상태가 시그널 상태가 될때 까지 대기 및 에빈트 객체의 신호 상태를 감지

     - cEvents: 대기할 이벤트의 개수

     - &lphEvent: 대기할 이벤트 배열

     - fWaitAll: TRUE이면 모든 객체가 시그널 상태가 되기 전까지 대기

     - dwTimeout: 이벤트 객체 대기상태 대기 시간

     - fAlertable: 스레드 실행에 대한 입출력 완료 루틴 설정

   - 발생할 이벤트의 크기는 STL을 사용해 사이즈를 알 수 있고 이벤트 또한 알 수 있음

     - 하나의 이벤트만 확인하므로 FALSE 및 무한정으로 대기

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성   
	// 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장
	while (true)
	{
		// 이벤트 상태가 시그널 상태가 될때 까지 대기 및 에빈트 객체의 신호 상태를 감지
		DWORD Index = WSAWaitForMultipleEvents(socketEventVector.size(), &socketEventVector[0], FALSE, WSA_INFINITE, FALSE);
		if (Index == WSA_WAIT_FAILED) continue;
        
		// 몇 번째 인덱스에서 이벤트가 발생했는지 알 수 있음
		Index -= WSA_WAIT_EVENT_0;
	}
    
	// Close WSA
}

 - 최종적으로 구한 인덱스를 통해 발생한 이벤트의 종류를 알아냄

int WSAEnumNetworkEvents(SOCKET s,WSAEVENT hEventObject,LPWSANETWORKEVENTS lpNetworkEvents);

   - 발생한 이벤트 종류 기록을 채워넣을 구조체 (발생한 에러 또한 담길 수 있음)

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성   
	// 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장
	while (true)
	{
		// 이벤트 상태가 시그널 상태가 될때 까지 대기 및 에빈트 객체의 신호 상태를 감지 및 이벤트 발생 확인
		
		// 발생한 이벤트 종류 기록을 채워넣을 구조체 (발생한 에러 또한 담길 수 있음)
		WSANETWORKEVENTS wsaNetEvents;
		if (WSAEnumNetworkEvents(socketVector[Index].socket, socketEventVector[Index], &wsaNetEvents) == SOCKET_ERROR) continue;
	}
    
	// Close WSA
}

 - 클라이언트 접속 이벤트 발생 (FD_ACCEPT 이벤트 처리)

   - 접속이 성공하면 클라이언트에 맞는 이벤트 생성 및 클라이언트 소켓과 묶음

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성   
	// 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장
	while (true)
	{
		// 이벤트 상태가 시그널 상태가 될때 까지 대기 및 에빈트 객체의 신호 상태를 감지 및 이벤트 발생 확인
		// 발생한 이벤트 종류 기록을 채워넣을 구조체 (발생한 에러 또한 담길 수 있음)

		// 클라이언트 접속 이벤트 발생 - FD_ACCEPT 이벤트 처리
		if (wsaNetEvents.lNetworkEvents & FD_ACCEPT)
		{
			if (wsaNetEvents.iErrorCode[FD_ACCEPT_BIT] != 0) continue;
			// 접속 성공
			SOCKADDR_IN clientAddr;
			int32 addrLength = sizeof(clientAddr);
			SOCKET clientSocket = ::accept(socketVector[Index].socket, 
				reinterpret_cast<SOCKADDR*>(&clientAddr), &addrLength);
			if (clientSocket == INVALID_SOCKET) continue;

			// 이벤트 생성 및 클라이언트 소켓과 이벤트를 묶음
			WSAEVENT clientEvent = WSACreateEvent();
			socketVector.push_back(Session{ clientSocket });
			socketEventVector.push_back(clientEvent);
			WSAEventSelect(clientSocket, clientEvent, FD_READ | FD_WRITE |FD_CLOSE);
		}
	}
    
	// Close WSA
}

 - READ 이벤트 검사

int main()
{
	// Init WSA, Socket Create, Server IP/HOST
	// Non-Blocking Socket, BIND, LISTEN
	// 이벤트 상태를 감지할 수 있는 이벤트 배열 및 소켓 배열 생성   
	// 생성한 Listen Socket 및 Event 를 묶고 벡터에 저장
	while (true)
	{
		// 이벤트 상태가 시그널 상태가 될때 까지 대기 및 에빈트 객체의 신호 상태를 감지 및 이벤트 발생 확인
		// 발생한 이벤트 종류 기록을 채워넣을 구조체 (발생한 에러 또한 담길 수 있음)
		// 클라이언트 접속 이벤트 발생 - FD_ACCEPT 이벤트 처리

		// READ 이벤트 검사
		if (wsaNetEvents.lNetworkEvents & FD_READ)
		{
			if (wsaNetEvents.iErrorCode[FD_READ_BIT] != 0) continue;
			// 서버에게 메세지를 보냄
			int32 recvLength = ::recv(socketVector[Index].socket, socketVector[Index].recvBuffer, MAX_BUFFER, 0);
			if (recvLength <= SOCKET_ERROR)
				if (::WSAGetLastError() == WSAEWOULDBLOCK) continue;

			cout << socketVector[Index].recvBuffer << endl;

		}
	}
    
	// Close WSA
}

 

2. Client

https://choiprogramming.tistory.com/110

 

[SERVER] Select

1. Select 1.1 Non-blocking Socket의 문제 - 함수의 결과를 예상X - 패킷 수신 여부와 관계없이 바로 리턴 → buf의 상태가 어떤지 알 방법X - 소켓이 Read/Write 할 수 있는 상태인지 아닌지 판별해 주는 select

choiprogramming.tistory.com

저작자표시 (새창열림)

'Create Game > [Window API] Game Client & Game Server' 카테고리의 다른 글

[SERVER] IOCP  (0) 2023.01.14
[SERVER] Overlapped I/O  (0) 2023.01.14
[SERVER] Select  (1) 2023.01.12
[SEVER] Non-blocking Socket  (1) 2023.01.11
[SEVER] UDP Server  (0) 2023.01.10
    'Create Game/[Window API] Game Client & Game Server' 카테고리의 다른 글
    • [SERVER] IOCP
    • [SERVER] Overlapped I/O
    • [SERVER] Select
    • [SEVER] Non-blocking Socket
    GameChoi
    GameChoi

    티스토리툴바