본문으로 바로가기
728x90
반응형

오늘은 C언어의 네트워크 프로그래밍에서 사용하는 소켓 옵션 제어에 대해 알아보겠습니다.

 

네트워크 프로그래밍을 하다보면 socket, bind, listen 함수는 많이 사용해보셨을겁니다.

 

이런 함수들은 소켓의 기본 기능을 담당했지만, 소켓에 대한 옵션을 설정 할 수는 없습니다.

 

소켓 옵션을 설정하려면 getsockopt, setsockopt 함수를 사용합니다.

 

먼저 두 함수에 대해 알아보겠습니다.

 

int getsockopt(int socket, int level, int option_name, void *restrict option_value, socklen_t *restrict option_len);

int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);

 

첫번째 인자 ( socket ) : socket으로 소켓 디스크립터입니다.

두번째 인자 ( level ) : 프로토콜 레벨을 의미합니다. (SOL_SOCKET, IPPROTO_IP, IPPROTO_TCP, IPPROTO_IPV6)

세번째 인자 ( option_name ) : 옵션의 세부대상을 의미합니다. 두번째 인자에 따라서 다양한 옵션이 있습니다.

네번째 인자 ( option_value ) : void 포인터 타입으로, 각각의 옵션에 따라서 다양하게 타입을 넣을 수 있습니다.

다섯번째 인자 ( option_len ) : option_value의 크기를 나타냅니다.

 

소켓 옵션의 종류는 엄청나게 많습니다.

 

그 중에서 프로토콜 레벨 SOL_SOCKET에서 많이 사용하는 옵션 몇 개만 포스팅해보겠습니다.

 

1. SO_REUSEADDR

 

서버에서 사용하는 것으로, 서버가 강제 종료하거나, 오류로 종료가 되었다면 시스템은 서버측 프로그램에 접속해있던 클라이언트를 모두 끊어버립니다.

 

대부분의 서버들은 이 옵션을 사용합니다.

 

만약 클라이언트가 접속하고 있는 상태에서 서버가 종료가 되어버린 후, 서버가 다시 시작되어 소켓을 bind할 경우에 사용중이라는 에러가 뜹니다.

 

왜냐하면 시스템에서는 연결중인 세션들을 서버가 종료되었다고 해서 바로 끊어버리지는 않습니다.

 

시간이 지나면 죽은 세션이라고 판단하고 세션을 끊어버립니다.

 

이렇게 되면 서버는 소켓을 bind 하지 못하여 다른 클라이언트과 연결이 불가능합니다.

 

이 옵션을 사용하면 이런 문제는 없습니다.

 

기본값은 off입니다. 값을 1로 설정하면 on이 됩니다.

 

ex ) 

int sock_opt = 1;

socklen_t sock_len = sizeof(sock_opt);

 

setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sock_len);

 

2. SO_RCVBUF, SO_SNDBUF

 

SO_RCVBUF는 수신 버퍼의 크기, SO_SNDBUF는 송신 버퍼의 크기를 뜻합니다.

 

이 옵션을 사용하여 버퍼의 크기를 설정할 수 있습니다.

 

버퍼의 크기가 크다고 좋을까요?

 

상황에 따라 다릅니다.

 

버퍼의 크기가 크다면 소켓을 만들수록 메모리를 많이 먹게 됩니다. 

 

또한, 소켓을 자주 만들고 닫게되면, 메모리 할당과 해제에 오버헤드가 발생합니다.

 

이 옵션을 사용해보면서 느낀건데, 모든 시스템이 이 옵션이 적용되지는 않습니다.

 

참고하시기바랍니다.

 

ex )

int sock_opt = 12345;

socklen_t sock_len = sizeof(sock_opt);

 

setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sock_opt, sock_len);

 

3. SO_RCVTIMEO, SO_SNDTIMEO

 

타입 아웃 옵션입니다. 두 옵션의 차이는 눈치 채셨을겁니다.

 

수신의 경우 recv, recvfrom, accept 등, 송신의 경우 send, sendto, connect 등 과 같은 함수는 블럭이 될 수 있는 함수입니다.

 

이벤트가 발생하지 않으면 오랫동안 블럭이 됩니다.

 

그렇기 때문에 블럭인 상황을 빠져나오려면 타임 아웃이 필요합니다.

 

그럴때 사용하는 옵션입니다.

 

설정한 시간동안 리턴이 되지 않으면 errno가 EAGAIN으로 리턴됩니다.

 

ex)

struct timeval tv_timeo = { 5, 500000 }; /* 5.5초 앞의 인자는 sec, 뒤의 인자는 usec*/

setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv_timeo, sizeof(tv_timeo));

 

4. SO_LINGER

 

TCP 소켓에서만 사용가능 하고, TCP연결을 끊을 때, 송신 버퍼에 데이터가 완전히 전송되었는지 확인하기 위해 사용하거나, 연결을 강제로 취소하여 TIME_WAIT 상태로 만들지 않는 용도로 사용합니다.

 

이 옵션도 많이 사용합니다.

 

5. SO_KEEPALIVE

 

이 기능은 일정 시간마다 TCP 연결 상태를 검사하는 옵션입니다.

 

보통 30분 ~ 2시간이 기본값이고, 설정에 따라서 변경이 가능합니다.

 

기능이 설정되면 일저 시간마다 상태 확인용 패킷을 보내어 연결에 문제가 없는지 확인합니다.

 

오늘 포스팅은 여기까지 하겠습니다.

728x90
반응형