TCP/IP 서버를 만들때는 다음과 같은 방법으로 만들게 된다.

1. 소켓 생성
2. bind
3. listen
4. accept 로 클라이언트 소켓 생성

소켓 프로그램을 처음하는 사람들이 겪게 되는 의문 중의 하나는 무엇에다가 묶고(bind), 듣기전까지는 어떤 일이 일어나길래 들어야(listen)하는가인데, 여기에는 발상의 전환이 필요하다. 일반적으로 파일을 열고 파일에서 읽는 과정을 생각해보면, 이미 경로라는 구별되어 있는 개체가 존재하고 그것을 다루기 위한 기술자(descriptor)를 만들어 기술자를 모든 파일 관련 입출력 함수에 인자로 넘기게 되는데, 소켓 프로그램은 그 반대라는 것이 중요하다. 기술자(socket)를 먼저 만들고, 그 기술자를 구별될 수 있는 경로 혹은 주소에 가져다가 붙이는 일을 한다.

그 이유는 기술자 혹은 소켓의 개념과 주소의 개념이 각각 내부적인 것과 외부적인 것을 대표하는 개념이 이미  OS 초창기부터 존재해 왔고 , 기존의 풍부한 기술자 기반의 시스템 호출과 유사하게 가져가려는 심미적인 설계 때문에 생긴 것이라 할 수 있다.

listen 이라는 것은 쉽게 이야기하면, 이제부터 외부의 접속을 듣겠다, 받아들일 준비 상태로 만들어라는 뜻이겠지만, 보다 기술적인 얘기를 하자면, listen 상태에 들어 있는 소켓은 응용 프로그램이 accept를 하는 것과 상관없이 커널에서 접속에 관계된 3 way handshaking을 구동시키라는 뜻이된다. 중요한 것은 accept와 상관없이 일어나는 것이며, accept는 그렇게 접속과정을 끝낸 소켓을 큐에서 꺼내어 특정 주소에 bind 되어 있는 소켓을 만들어 내는 일을 하는 것이다.

그러면, 일반적으로 서버 소켓을 만들때 사용하는 재사용 가능한 소켓은 언제 설정해 주어야 하는가?

1. 소켓 생성
2. setsockopt( s, SOL_SOCKET, SO_REUSEADDR ... );
3. bind
4. listen
5. accept 로 클라이언트 소켓 생성

bind 작업에 들어갈 때, 묶어 주는 주소에 대해 서버 소켓이 listen 상태에서 벗어나는 순간 바로 (주소에 해당하는 ESTABLISHED 혹은 TIME_WAIT 상태로 남아 있는)가 있어도) 다시 접속가능한 bind 를 지정하기 위해서 소켓 옵션의 설정은 bind 이전에 해야하는 것이 옳다. 재사용가능 한 것이 소켓 옵션이 아니라 주소에 대한 것이므로 소켓에 옵션을 실어 bind 시스템 호출을 해서 넘기는 것이다. 즉, 다음은 올바른 사용법이 아니라는 것이다.

1. 소켓 생성
2. bind
3. setsockopt( s, SOL_SOCKET, SO_REUSEADDR ... );
4. listen
5. accept 로 클라이언트 소켓 생성

물론 구현에 따라 위 순서로 해도 동작가능할 수 있다. 하지만, 의미상 그렇지 않다는 것을 알고 사용하자.

신고

+ Recent posts