본문 바로가기

공부/tcp/ip 프로그래밍

동기, 비동기, 블로킹, 논블로킹

반응형

[출처] 동기, 비동기, 블러킹, 논 블러킹 (C언어를 배우자) |작성자 bilope

1. 동기(同期, synchronous)

동기의 사전적 의미는 "동시에 발생하는 것" 입니다.
클라이언트서버에 "저 지금 접속했습니다." 라고 요청했다면,
서버가 "아 그래? 너 접속했구나? 너 접속했다고 해줄께." 라고 대답할 때까지 클라이언트가 무릎 꿇고 가만히 기다려야합니다.
"이게 동시에 발생하는 것과 무슨 상관이 있지?"
라고 생각하시는 분들을 위해, 간단한 예를 들어 설명해드리겠습니다.

제가 고또님께 꼭 드릴 말씀이 있어 전화를 걸었습니다.
그런데 고또님이 전화를 받지 않으십니다.
저는 고또님이 전화를 받으실 때까지 계속 전화기를 붙잡고 기다립니다.

이 과정에서 저는 전화기를 붙잡고 기다리느라 아무런 행동도 할 수 없습니다.
(물론 코를 판다던가, 하품을 한다던가 하는 자잘한 행동들은 예외지만요.)

이를 적용하면, 클라이언트는 서버가 답하기 전까지 죽어버린다는 겁니다.

그러니 클라이언트가 언제 요청할지, 서버가 언제 답할지를 프로그램 설계시에 명확히 해야겠습니다.

이를 동시에 요청하고 응답한다고 말할 수도 있지 않을까요?
(물론 완벽히 동시는 아니지만, "거의" 동시니까요 ^^)




2. 비동기(非同期, asynchronous)

비동기의 사전적 의미는 "동시에 발생하지 않는 것" 입니다.
동기 앞에 아닐 비(非)가 붙었으니 당연하려나요? ^^;
이번에는 바로 예를 들어보겠습니다.

제가 고또님께 꼭 드릴 말씀이 있어 전화를 걸었습니다.
그런데 고또님이 전화를 받지 않으십니다.
저는 전화기를 스피커폰으로 전환하고 게임을 하면서 기다립니다.

동기와는 다르게 전화를 걸면서 게임을 하고 있습니다!

이를 프로그램에 적용해볼까요?

클라이언트는 서버에게 요청을 하고, 그 요청이 오기 전까진 다른 일을 할 수 있습니다.

즉, 서버가 응답하지 않는다고해서 프로그램이 죽어버리지는 않는다는 것이죠!
(물론 서버가 응답하지 않으면 프로그램을 종료시킨다던가의 루틴은 제외하구요..)




※ "그럼 동기보다 비동기가 무조건 좋은 것이 아니냐?"

라고 하시는 분들이 계실 것 같습니다.

아닙니다. 동기와 비동기가 둘 다 존재하는 이유는 동기와 비동기가 각각 쓰임새가 다르기 때문입니다.




3. 블로킹(blocking)

블로킹"무언가를 막는다"는 뜻입니다.
무엇을 막을까요?
동기식으로 설계를 했을 때, 응답이 오기 전까지 다음 루틴으로 넘어가는 것을 막습니다.

즉, 고또님이 전화를 받으시기 전까지(응답이 오기 전까지)
다른 행동(다음 루틴)을 못하도록 막는 것이죠.

다음에 소켓 프로그래밍에 대한 예제에서 다시 설명드리겠지만,

socket 함수로 소켓을 생성하면 기본적으로 블로킹 모드로 소켓이 생성됩니다.

이 상태에서 send 함수나 recv 함수를 사용하게 돼면 응답이 있기 전까지 return을 하지 않습니다.

함수에서 계속 머뭅니다.




4. 논-블로킹(non-blocking)

앞에 "~이 아닌" 이라는 접두어 "non"이 붙었으니 "무언가를 막지 않는다."라는 뜻이겠죠?
블로킹과는 반대로 비동기식으로 설계했을 때, 응답이 왔든 안왔든 다음 루틴으로 넘어가는 것을 막지 않습니다.

고또님께 전화를 걸어 놓고(서버에 요청하고)
스피커 폰으로 전환한 뒤(서버에서 응답이 오든 안오든)
게임을 하면서(다음 루틴을 실행하면서)
고또님이 전화를 받으시면(서버에서 응답하면)
고또님과 대화하면 되는거죠.(서버와 통신)

이 또한 다음에 다시 설명드리겠지만,

fcntl 함수로 소켓을 논-블로킹 상태로 만들 수 있습니다.

이때에, send 함수와 recv 함수를 실행했을 때, 보내거나 받을 데이터가 있으면 보내고 받지만,

그렇지 않을 경우 errno.h 헤더파일에 존재하는 errno 변수에 상태를 넣어주므로

errno 변수의 값을 판단하여 어떤 행동을 할지 설계하면 됩니다.

꼭 이 방법 뿐만 아니라 다른 많은 방법으로도 비동기식으로 설계가 가능하다고 합니다.

---------------------------------


열혈강의 tcp/ip 소켓프로그래밍 p385

소스에서 91줄 ~95줄

setnonblockingmode()는 소켓을 논블로킹상태로 설정하는 것

read함수나 write함수가 background로 실행되어 소스와는 별개로 진행처리하게 됨

69줄 read함수의 반환 값은 변수에 저장되므로 변수에 저장된 반환 값이 무엇인지 확인하고 그에 맞는 처리를 if절을 통해 처리

 

논블로킹상태로 하지 않으면(=블로킹상태)

socket의 입력버퍼에 내용이 없어서 비워있는 경우에 read()함수를 호출하면 입력버퍼에서 정보를 받을 때까지 계속 기다림 

정보를 받기 위해서 입력버퍼를 계속 쳐다보고 입력버퍼에 정보가 채워질 때까지 계속 기다리게 됨

반응형