더북(TheBook)

구동 직후 리스닝 스레드는 소켓을 만들고 바인딩한 다음, 리스닝을 걸고 accept()를 호출한다. accept()는 클라이언트가 접속하기 전까지 블로킹 상태에 빠진다. 클라이언트가 접속하면 accept() 함수는 새 소켓을 리턴하고 복귀한다. 서버 프로세스는 이제 새 소켓용으로 스레드를 하나 만드는데, 이 스레드는 반복해서 recv()를 호출한다. recv() 함수는 클라이언트가 데이터를 보내기 전까지 블로킹 된다. 클라이언트가 데이터를 보내면 recv()가 블로킹 상태를 빠져나와 스레드 수행을 재개하며, 일종의 콜백 메커니즘으로 수신된 데이터를 메인 스레드에 보내준 다음 루프를 재개하여 recv()를 또 호출한다. 그동안 리스닝 소켓은 또 자기만의 블로킹 상태에서 다른 접속을 기다린다. 메인 스레드는 이와 상관없이 게임 시뮬레이션을 수행할 수 있다.

이렇게 구현하면 잘 돌아가기는 하지만 클라이언트마다 하나씩 스레드를 할당해야 한다는 단점이 있다. 그러면 클라이언트 수가 증가할수록 대처하기 힘들어진다. 또한, 클라이언트 데이터가 병렬적으로 한꺼번에 여러 스레드에서 들어올 수 있으므로 시뮬레이션에 데이터를 안전하게 전달하기 까다로운 문제도 있다. 마지막으로 스레드가 데이터를 받는 도중, 메인 스레드가 같은 소켓에 데이터를 보내려 하면 여전히 블로킹될 수밖에 없는 맹점이 있다. 이런 문제가 극복하기 그다지 어려운 문제는 아니지만 훨씬 간편한 대안이 있다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.