한남대학교 컴퓨터공학과 소프트웨어공학실험실 최 용 준 Socket Option 한남대학교 컴퓨터공학과 소프트웨어공학실험실 최 용 준 한남대학교 컴퓨터공학과 컴퓨터 네트워크 실험실
이 장의 목적 getsockopt(2)을 이용하여 소켓 옵션값을 가져오기 setsockopt(2)을 이용하여 소켓 옵션값을 지정하기 필요한 소켓 옵션을 찾아내어 적용하는 방법
내용 소켓 옵션 가져오기 – getsockopt() 소켓 옵션 지정하기 – setsockopt() 소켓형태 ( SO_TYPE ) 가져오기 – stream, dgram 소켓 옵션의 역할 SO_REUSEADDR SO_LINGER SO_KEEPALIVE SO_BROADCAST -> 13장 SO_OOBINLINE -> 14장 SO_PASSCRED & SO_PRERCRED -> 17장
Getsockopt() Synopsis & Protocol level, Option Name Option Name SO_NODELAY SOL_TCP SO_ERROR SOL_SOCKET SO_TYPE SO_RCVBUF SO_SNDBUF SO_OOBINLINE SO_BROADCAST SO_LINGER SO_KEEPALIVE SO_REUSEADDR Option Name Protocol level #include <sys/type.h> #include <sys/socket.h> int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
Getsockopt() 예제 12.1 초기화 소켓생성 send 버퍼크기 확인 receive 버퍼크기 확인 소켓 종료 Variable initialize socket() getsockopt() – SO_SNDBUF getsockopt() – SO_RCVBUF close()
Getsockopt() 적용 초기화 (line 31~35) 소켓 생성 (line 40) int z; int s = -1; /* 소켓 초기화 */ int sndbuf=0; /* 보낼 버퍼의 크기 */ int rcvbuf=0; /* 받을 버퍼의 크기 */ socklen_t optlen; /* 옵션의 길이 */ s = socket(PF_INET, SOCK_STREAM, 0);
assert(optlen == sizeof sndbuf); Getsockopt() send 버퍼의 크기 알아내기 (line 44~52) 버퍼 검증 (line 54) optlen = sizeof sndbuf; z = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen); if ( z ) bail("getsockopt(s, SOL_SOCKET, SO_SNDBUF)"); assert(optlen == sizeof sndbuf);
assert(optlen == sizeof rcvbuf); Getsockopt() receive 버퍼의 크기 알아내기 (line 56~64) 버퍼 검증 (line 66) optlen = sizeof rcvbuf; z = getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen); if ( z ) bail("getsockopt(s, SOL_SOCKET, SO_RCVBUF)"); assert(optlen == sizeof rcvbuf);
Getsockopt() 출력하기 (line 71~75) printf("Socket s : %d\n", s); printf(“ Send buf: %d bytes\n", sndbuf); printf(“ Recv buf: %d bytes\n", rcvbuf);
Getsockopt() 결과 [yong8e@selinux chap12]$ make getsndrcv gcc -c -D_GNU_SOURCE -Wall -Wreturn-type getsndrcv.c gcc getsndrcv.o -o getsndrcv [yong8e@selinux chap12]$ ./getsndrcv Socket s : 3 - Send buf: 65535 bytes - Recv buf: 65535 bytes
Setsockopt() 예제 12.2 초기화 소켓생성 send 버퍼크기 지정 receive 버퍼크기 지정 소켓 종료 Variable initialize socket() setsockopt() – SO_SNDBUF setsockopt() – SO_RCVBUF getsockopt() – SO_SNDBUF getsockopt() – SO_RCVBUF close()
Setsockopt() 적용 초기화 (line 29~35) 소켓 생성 (line 40) int z; int s = -1; /* 소켓 초기화 */ int sndbuf=0; /* 보낼 버퍼의 크기 */ int rcvbuf=0; /* 받을 버퍼의 크기 */ socklen_t optlen; /* 옵션의 길이 */ s = socket(PF_INET, SOCK_STREAM, 0);
Setsockopt() 버퍼 크기 설정 sndbuf = 5000; /* send 버퍼의 크기 설정 */ z = setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof sndbuf); if ( z ) bail("setsockopt(s, SOL_SOCKET, SO_SNDBUF)"); rcvbuf = 8192; /* receive 버퍼의 크기 설정 */ z = setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof rcvbuf); bail("setsockopt(s, SOL_SOCKET, SO_RCVBUF)");
Setsockopt() 출력하기 (line 71~75) printf("Socket s : %d\n", s); printf(“ - Send buf: %d bytes\n", sndbuf); printf(“ - Recv buf: %d bytes\n", rcvbuf);
Setsockopt() 결과 [yong8e@selinux chap12]$ make setsndrcv gcc -c -D_GNU_SOURCE -Wall -Wreturn-type setsndrcv.c gcc setsndrcv.o -o setsndrcv [yong8e@selinux chap12]$ ./setsndrcv Socket s : 3 Send buf: 10000 bytes Recv buf: 16384 bytes 5000 byte -> 10,000 byte 참고) /usr/src/linux-2.2.16/net/core/socket.c
참고 SO_RCVBUF & SO_SNDBUF /usr/src/linux-2.2.10/net/core/socket.c case SO_SNDBUF: if (val > sysctl_wmem_max) val = sysctl_wmem_max; sk->sndbuf = max(val*2, 2048); sk->write_space(sk); break; case SO_RCVBUF: if (val > sysctl_rmem_max) val = sysctl_rmem_max; sk->rcvbuf = max(val*2, 256);
getsockopt() – SO_TYPE 예제 12.3 초기화 소켓생성 버퍼타입 확인 소켓 종료 Variable initialize socket() getsockopt() – SO_TYPE close()
So_type 옵션 적용 소켓타입 가져오기 결과 출력하기 z = getsockopt(s, SOL_SOCKET, SO_TYPE, &so_type, &optlen); printf(" SO_TYPE : %d\n", so_type);
So_type 옵션 결과 [yong8e@selinux chap12]$ make gettype gcc -c -D_GNU_SOURCE -Wall -Wreturn-type gettype.c gcc gettype.o -o gettype [yong8e@selinux chap12]$ ./gettype Socket s : 3 SO_TYPE : 1 SOCK_STREAM = 1 SOCK_DGRAM = 2 SO_TYPE = 1; /* SOCK_STREAM */ SO_TYPE = 2; /* SOCK_DGRAM */
Forked Server connected SO_REUSEADDR 옵션 Connect 존재하는 프로세스 Server listening on 192.168.0.1 port 9099 (PID 926) Forked Server connected To client (PID 927) telnet 192.168.0.2 port 1035 Connect Connect Socket Fork()
SO_REUSEADDR 옵션 역할 조건 소켓의 재사용 같은 IP 주소와 port를 가진 소켓이 없어야한다. 같은 IP 주소와 port를 가진 소켓이 있는 경우 SO_REUSEADDR 옵션이 TRUE로 셋팅되야 한다.
SO_REUSEADDR 옵션 Synopsis #define TRUE 1 #define FALSE 0 int z; /* 상태 코드 */ int s; /* 소켓 번호 */ int so_reuseaddr = TRUE; z = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof so_reuseaddr);
SO_LINGER 옵션 역할 운영모드 소켓이 close() 함수를 호출하였을 때 소켓을 어떻게 종료할 것인지를 제어한다. Struct linger { int l_onoff; int l_linger; }
SO_LINGER 옵션 운영모드 l_onoff : FALSE l_onoff : TRUE , l_linger : nonzero L_linger 무시, close() 함수 호출하여 소켓 종료 l_onoff : TRUE , l_linger : nonzero 타임아웃(지정된 시간)이 적용, 시간안에 데이터 전송이 완료되면 성공된 값이 리턴, 전송이 완료되지 않으면 에러 발생하여 errno는 EWOULDBLOCK 반환 l_onoff : TRUE , l_linger : zero 연결 취소, 데이터 받던 것도 폐기
SO_LINGER 옵션 Synopsis #define TRUE 1 #define FALSE 0 int z; /* 상태 코드 */ int s; /* 소켓 번호 */ Struct linger so_linger; So_linger.l_onoff=TRUE; So_linger.l_linger=30; z = setsockopt(s, SOL_SOCKET, SO_LINGER, &so_keepalive, sizeof so_keepalive); If (z) perror(“setsockopt(2)”);
SO_KEEPALIVE 옵션 역할 세션이 idle인 상태일때 클라이언트의 상태를 확인하여 서버에 의해 소켓을 종료시킨다. Probe message 를 원격 단말기에 보낸다. 활동이 있은 후 두시간 뒤에… 원격 단말기의 반응 응답을 한다. 세션에 대한 아무런 일도 하지 않음을 응답한다. ECONNRESET 에러 반환 반응이 없다. ETIMEOUT 에러 반환 EHOSTUNREACH 에러 반환
SO_KEEPALIVE 옵션 Synopsis #define TRUE 1 #define FALSE 0 int z; /* 상태 코드 */ int s; /* 소켓 번호 */ int so_keepalive = TRUE; z = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive, sizeof so_keepalive); If (z) perror(“setsockopt(2)”);
SO_BROADCAST 옵션 Synopsis #define TRUE 1 #define FALSE 0 int z; /* 상태 코드 */ int s; /* 소켓 번호 */ int so_broadcast; So_broadcast = TRUE; z = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &so_broadcast, sizeof so_broadcast); If (z) perror(“setsockopt(2)”);
SO_OOBINLINE 옵션 Synopsis #define TRUE 1 #define FALSE 0 int z; /* 상태 코드 */ int s; /* 소켓 번호 */ int so_oobinline; So_oobinline = TRUE; z = setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &so_oobinline, sizeof so_oobinline); If (z) perror(“setsockopt(2)”);
SO_PASSCRED, SO_PRERCRED 옵션 역할 PF_UNIX(PF_LOCAL) 소켓에서만 사용 17장에서 논의
요약 Getsockopt() 함수를 이용하여 소켓의 옵션값을 가져오는 방법에 대해… Setsockopt() 함수를 이용하여 소켓이 필요로 하는 옵션을 지정하는 방법에 대해… 소켓의 옵션에는 어떠한 것들이 있는지…