서버 프로그램 종료에 관해서 다시 질문드립니다
안녕하세요, 어제 1588번 글에서 서버 프로그램을 깔끔하게 종료할 수 있는 방법에
대해서 문의를 했던 석입니다.
답변을 성심껏 해 주신 배성남님께 특별히 감사드립니다.
배성남님께서 조언해 주신 방법중에 제가 쓰고 있는 버클리 소켓에 적절한 방법은
nonblocking 소켓 방법인것 같습니다. 왜냐하면 제시해주신 소스 코드중에서
/*
* Make socket non-blocking
*
*/
if (fcntl(incoming_socket, F_SETFL, O_NDELAY) < 0) {
perror("Can't set socket to non-blocking");
exit(0);
}
이 부분만을 제외하고는 나머지가 제가 이미 짜놓은 프로그램과 거의 일치하기
때문입니다.
저는 제 프로그램에서 단지 위의 소스 부분만을 설정하지 않았는데,
위 소스의 주석을 보니 소켓을 '비봉쇄 (non-blocking)'로 설정한다고 쓰여져 있네요.
나름대로 조사를 해 보았으나 위의 구문이 accept() 함수 때문에 기다리고 있는 상태에
어떤 다른 효과를 주는지 잘 이해하지 못하겠습니다. STEVENS의 UNIX NETWORK
PROGRAMMING에서도 이 부분에 대해서 나와는 있으나 제가 가지고 있는 책은 한글
번역본이라서 그런지 잘 이해가 가질 않네요.
------------------------------------------------------------------------------------------------------------
그리고 제가 짠 프로그램의 개요를 좀더 자세하게 밝혀 드려야 더욱 도움이 되는
고마운 조언들이 들어 올 것 같군요.
저는 인터넷을 이용해서 '양방향적인' 통신을 원활히 하기 위한 프로그램을
만들고 있습니다.
단방향적인 서버와 클라이언트의 개념이 아니라, 양방향적인 통신을
원하는 것이기 때문에 한 프로그램이 서버의 역할을 수행함과 동시에 클라이언트의
역할을 수행해야 합니다.
그러니까.. 인터넷을 통해서 다른 클라이언트가 어떤 정보를 요청하면 그 요청에 적절히
응답할 수 있는 서버 프로그램이 돌아가면서, 또 자기가 어떤 정보가 필요하면 다른
서버에게 그 정보를 요청할 수 있는 클라이언트 프로그램이 동시에 같은 프로그램
안에 존재해야하는 것입니다.
그래서 저는 우선 한 프로그램안에 서버와 클라이언트의 스레드를 각각 만들었습니다.
멀티 스레드 프로그램을 하고 있는 것입니다.
물론 이 프로그램은 사용자의 명령도 받을 수 있어야 하기 때문에 메인 프로그램에서
그런 역할을 수행하도록 프로그램 하고 있습니다.
그러니까 동시에 3개의 스레드가 존재하고 있다는 것이지요.
그러다가 사용자로 부터 종료 메시지를 받으면 메인 스레드나 클라이언트 스레드는
별로 어렵지 않게 종료할 수 있으나 서버 스레드는 앞에서 질문했듯이 accept() 함수에
걸려서 종료 메시지를 받아들이지 못하는 것입니다.
따라서 원활한 종료가 되지 않고 프로그램에 멈추는 현상이 일어납니다.
여러분의 고마운 조언이 필요합니다.
그럼 이만...^^/
Re^2: 서버 프로그램 종료에 관해서 다시 질문드립니다
아.. 그렇군요, 한번 시도해보겠습니다.
훌륭한 조언에 정말 감사드립니다.
Re: Blocking과 Non-Blocking의 차이
Blocking과 Non-Blocking의 차이를 설명하기 좋은 그림이
UNIX NETWORK PROGRAMMING에 있어서 인용을 해봅니다.
일반적으로 사용하는 accept는 상태편이 접속을 하기 전까지
http//www.ezdoum.com/upload/linux_io_block.gif
처럼 블럭상태로 있습니다.
그런데 이것을
if (fcntl(incoming_socket, F_SETFL, O_NDELAY) < 0) {
perror("Can't set socket to non-blocking");
exit(0);
}
이렇게 지정을 하게 되면..
http//www.ezdoum.com/upload/linux_io_nonb.gif
그림 처럼 바로 접속이 있던 없던간에 바로 리턴을 하게
되는 것이죠..
접속이 있는 경우라면, blocking 모드의 accept와 동일한
동작을 하지만, 컨넥션 대기중인 fd가 아니라면
-1을 리턴하고 errno로 EAGAIN or EWOULDBLOCK를
주게 됩니다.
즉... non-blocking 모드로 하면
무한루프를 돌면서 계속적으로 accept를 호출해주어야 하는 것이지요.
(무한루프 속에서 -1을 리턴한 경우 errno가
EAGAIN or EWOULDBLOCK가 아니고 다른 경우라면,
accpet오류니까 루프를 멈추고 오류 처리를 해주어야 겠네요)
제가 예제로 올린 소스에서는 무한 루프가 CPU를 많이
잡아 먹으니까 sleep(1)이라는 지연시간을 두어서
cpu를 반납하는 모습을 볼수있씁니다.
암튼 제가 올린 두개의 그림을 보시면 차이를
아실듯 싶네요
ps.
참고로 Linux I/O Models관련해서 자료가 있어서
알려드립니다.
http//www.ezdoum.com/stories.php?story=02/07/24/9527258
Blocking I/O
Non-blocking I/O
I/O Multiplexing
Signal driven I/O
Asynchronous I/O
요런 방법들이 있지요.. ^^
댓글 달기