안녕하세요.
|
백엔드 개발자 이재윤입니다.

thumbnail
클라이언트 콘솔 입력 스레드 분리하기

클라이언트 스레드 관리 요약 클라이언트에서 전투 시작 시 콘솔 입력 + 패킷 처리가 동시에 실행이 되지 않았던 이유는 콘솔 입력 작업을 중복으로 큐에 추가하여, 모든 스레드가 블로킹 됐기 때문이다. 문제 상황 boost asio를 이용해 소켓 프로그래밍을 구축했습니다. 클라이언트의 스레드 구조는 아래와 같습니다. 4개의 작업스레드를 생성하고, io_context에 post된 작업을 스레드가 가져가서 작업을 하는 형태입니다. post 되는 작업은 Send() : 콘솔 입력 + 패킷 전송 Receive() : 패킷 수신 + 콘솔 출력 2개의 작업뿐입니다. 이해도 부족 처음 문제에 대해 다뤘던 문서 (읽어보지 않아도 됩니다..!) 요약 : 콘솔 입력 작업 / 패킷 수신 작업 2개의 작업이 존재하는데, 패킷 수신 작업이 1초마다 반복될 때, 두 작업이 동시에 진행되지 않았습니다. 정리했던 문서의 결과는 다음과 같습니다. getline() 함수는 블로킹 함수이고, 이로 인해 다른 스레드에서…

May 01, 2024
C++
Boost
Boost Work란?

Boost asio::io_service::work 란? Boost asio를 사용해 소켓 서버를 생성하면, 항상 io_service(지금은 io_context로 대체)를 사용하게 된다. 링크에선 work를 사용해야 하는 이유를 다루고 있다. 두 코드를 보면, 1. thread 생성, 2. 작업 post, 두 개의 작업이 존재하고 1번 코드는 1 → 2 (work 객체와 함께) 2번 코드는 2 → 1 의 순서로 코드 흐름이 이어진다. post는 IO Execution Context(여기선 io_service)에서 실행하겠다는 의미이다. 모든 context는 run을 실행해줘야 하는데, 여기선 thread를 생성하고 작업을 실행한다. 즉, 1번 코드는 IO Context run 이후 post 2번 코드는 post 이후 IO Context를 run 한다. 즉, 남은 작업이 존재하지 않아도 io_service가 run을 반환하지 않도록 도와주는 것이 work의 역할이다. ps. De…

March 23, 2024
C++
Boost
메모리 사이클 관리

메모리 사이클 기존 코드를 보면 아래와 같습니다. ProtocolPtr은 패킷을 주고 받을 때 사용하는 encode, decode가 구현된 객체입니다. 여기서 temp 변수는 Send() 함수에서 선언한 지역 변수이고, Send() 함수의 종료와 함께 소멸됩니다. Send() 함수는 비동기 함수인 boost::asio::async_write_some()을 호출합니다. 이때 Send() 함수가 종료된 이후 비동기 함수가 실행되고, 실행 후 SendHandle() 함수가 호출됩니다. 문제는 여기서 발생할 수 있습니다. 비동기함수는 temp->encode()를 매개변수로 전달받는데, temp는 Send() 함수가 종료되면 소멸됩니다. Send()의 종료 이후, 비동기함수가 실행될 때 temp의 메모리 안정성은 보장되지 않습니다. 때문에 메모리 이슈가 발생할 수 있고, 우리는 이 메모리를 관리해줄 필요가 있습니다. 람다에 캡쳐 비동기 함수에서 temp를 사용하기 위해 람다에 캡쳐를 사용합…

March 19, 2024
C++
소켓 통신 오류 디버깅 (패킷 처리 오류)

오류 발생 과정 Server ↔ Client 간의 소켓 통신 과정은 아래와 같습니다. Client: 를 통해 ID 설정 Server: 해당 Client의 ID를 설정하고 “set $ID Success”를 해당 Client에게 전송 () “$ID 님이 입장하셨습니다”를 모든 Client에게 전송 () Client: 를 통해 수신 이 과정에서 아래 에러가 발생했습니다. libc++abi: terminating due to uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument (해당 오류는 10번 시도 중 9번 정도로 발생했습니다) 오류 디버깅 Client와 Server의 핵심 코드는 아래와 같습니다 Thread 생성 시에 lock을 사용한 부분은 문제가 없었고, Receive 함수의 lock 호출과는 실행 시점이 분리되어 있습니다. 때문에 lock 관련 에러는 Receive …

March 07, 2024
C++