Professional Documents
Culture Documents
ch08 - 소켓 옵션
ch08 - 소켓 옵션
소켓 옵션
TCP/IP 응용 프로그램에 적용 가능한 다양한 소켓 옵션을
이해하고 활용한다.
개요 (1)
소켓 프로그래밍 모델
- 소켓을 통해 간접적으로 TCP, IP와 같은 하부 프로토콜을 이용하는 프로그램
- 지금까지 소켓함수를 그대로 호출 사용, 그러나 동일한 함수를 호출하더라도
소켓코드나 프로토콜 구현코드의 동작 변경 필요
응용 프로그램
소켓
소켓 코드
TCP UDP
프로토콜
IrDA Bluetooth ...
구현 코드
IP
2
개요 (2)
소켓 옵션
소켓 함수의 기본 동작을 변경
– 소켓 코드와 프로토콜 구현 코드를 세부적으로 제어
소켓 옵션의 종류
1) 소켓 코드가 처리하는 옵션
– 옵션을 설정하면 소켓 코드에서 해석하고 처리
2) 프로토콜 구현 코드가 처리하는 옵션
– 옵션을 설정하면 프로토콜 구현 코드에서 해석하고 처리
3
개요 (3)
소켓 옵션 설정(=변경)하기
int setsockopt (
SOCKET s,
int level, /* 옵션을 해석하고 처리하는 코드, 옵션레벨이라 함;
SOL_SOCKET: 소켓코드, IPPROTO_IP(TCP): IP(TCP)
int optname, // 옵션 이름 (표 참고)
const char* optval, // 옵션값을 가진 버퍼 주소
int optlen // optval이 가리키는 버퍼의 데이터크기
);
성공: 0, 실패: SOCKET_ERROR
4
개요 (4)
소켓 옵션 얻기
int getsockopt (
SOCKET s,
int level, // 옵션을 해석하고 처리하는 코드
int optname, // 옵션 이름 (표 참고)
char* optval, // 옵션값을 저장할 버퍼 주소
int* optlen /* 함수호출 전 초기값은 optval이 가리키는 버퍼의 크기;
함수호출 후 옵션 값의 크기가 저장됨 */
);
성공: 0, 실패: SOCKET_ERROR
5
소켓 옵션의 종류 (1)
level = SOL_SOCKET
optname optval get set 설명
SO_SNDBUF
int . . 소켓 송/수신 버퍼의 크기 설정
SO_RCVBUF
SO_SNDTIMEO
int . . 데이터 송/수신 함수 호출 시 타임아웃 값 설정
SO_RCVTIMEO
6
소켓 옵션의 종류 (2)
level = IPPROTO_IP
optname optval get set 설명
IP_ADD_MEMBERSHIP
ip_mreq{} . 멀티캐스트 그룹 가입과 탈퇴
IP_DROP_MEMBERSHIP
7
소켓 옵션의 종류 (2)
level = IPPROTO_IP
optname optval get set 설명
IP_ADD_MEMBERSHIP
ip_mreq{} . 멀티캐스트 그룹 가입과 탈퇴
IP_DROP_MEMBERSHIP
8
소켓 옵션의 종류 (3)
level = IPPROTO_IPV6
optname optval get set 설명
IPV6_ADD_MEMBERSHIP
ipv6_mreq{} . 멀티캐스트 그룹 가입과 탈퇴
IPV6_DROP_MEMBERSHIP
9
소켓 옵션의 종류 (4)
level = IPPROTO_TCP
optname optval get set 설명
10
SO_BROADCAST 옵션
용도
브로드캐스트 데이터 전송 기능 활성화
TCP 소켓에는 사용할 수 없고 UDP 소켓에만 사용 가능
사용 예
BOOL bEnable = TRUE;
retval = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
(char *)&bEnable, sizeof(bEnable));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
11
SO_BROADCAST 옵션
용도
브로드캐스트 데이터 전송 기능 활성화
TCP 소켓에는 사용할 수 없고 UDP 소켓에만 사용 가능
사용 예
BOOL bEnable = TRUE;
retval = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
(char *)&bEnable, sizeof(bEnable));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
12
SO_KEEPALIVE 옵션 (1)
용도
- TCP 프로토콜 수준에서 연결 여부를 확인하기 위해 상대 TCP에게 주기
적으로(약 2시간 간격) TCP 패킷을 보냄
- 이때, 상대 TCP의 반응은 2가지
1) 정해진 시간 내에 응답
TCP 연결에 문제 없음
2) 정해진 시간 내에 응답이 없거나 RST(reset) 패킷으로 응답
TCP 연결에 문제가 있으므로 자동으로 소켓을 닫음
사용 목적
서버가 TCP 연결이 끊어진 것을 감지하지 못하는 경우가 발생하고,
TCP 연결이 끊어진 소켓을 닫아 시스템 자원 낭비 방지
13
SO_KEEPALIVE 옵션 (2)
사용 예
14
SO_LINGER 옵션 (1)
용도
- closesocket() 함수의 디폴트 동작 변경
- 다음 경우 생각
위 에서 closesocket() 호출 시, 몇 가지 의문이 있음
Q) closesocket()는 언제 리턴? 송신 버퍼 데이터 전송 또는 삭제?
TCP 연결종료는 어떻게? 정상종료 or 강제종료?
이에 대해 3가지 방식을 생각해 볼 수 있음
① 함수는 곧바로 리턴; 송신 데이터를 백그라운드로 보냄; 정상종료
② 함수는 곧바로 리턴; 송신 데이터를 삭제; 강제종료
③ 송신 데이터를 모두 보냄; 정상종료; 함수 리턴
- SO_LINGER 옵션을 이용하여 ① ~ ③ 중 한 방식으로 동작시킴
15
SO_LINGER 옵션 (2)
옵션값
struct linger {
u_short l_onoff; /* option on/off */
u_short l_linger; /* linger time */
};
typedef struct linger LINGER;
사용 예
LINGER optval;
optval.l_onoff = 1; /* linger on */
optval.l_linger = 10; /* linger time = 10초 */
if(setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *)&optval, sizeof(optval)) == SOCKET_ERROR)
{
err_quit("setsockopt()");
}
16
SO_LINGER 옵션 (3)
용도
소켓의 송신 버퍼와 수신 버퍼 크기 변경
사용 예
int optval, optlen;
18
SO_SNDBUF, SO_RCVBUF 옵션 (2)
유의점
UDP 소켓은 언제든지 이 옵션을 이용해서 버퍼크기 변경가능하나,
TCP 소켓은 연결이 이루어지기 전에 해야 함,
즉,
TCP 서버에서는 listen(),
TCP 클라이언트에서는 connect()
호출 전에 설정 해야 함;
TCP 서버의 연결대기 소켓의 경우, 버퍼크기를 설정하면 accept()가
리턴하는 소켓도 동일한 크기로 설정됨
19
SO_SNDTIMEO, SO_RCVTIMEO 옵션 (1)
용도
- 기본 소켓은 블록킹 소켓으로 데이터 수신/전송 함수 호출 시 조건이 만족되지
않으면 무한정 블록되고, 이로 인해 교착 상태가 발생할 수 있음
- 이들 옵션을 사용하여 데이터 전송 함수(send(), recv(), sendto(),
recvfrom())가 작업 완료와 상관없이 일정 시간 후 리턴하도록 함
- 옵션 값은 정수형으로 ms 단위로 타임아웃 설정
20
SO_SNDTIMEO, SO_RCVTIMEO 옵션 (2)
사용 예
int optval = 3000;
retval = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
(char *)&optval, sizeof(optval));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
21
SO_REUSEADDR 옵션
용도
현재 사용 중인 IP 주소와 포트 번호를 재사용
– 현재 사용 중인 IP 주소와 포트 번호를 이용해 bind() 함수
를 (성공적으로) 호출할 수 있음
목적
TCP 서버 종료 후 재실행 시 bind( ) 함수에서 오류가 발
생하는 일을 방지
여러 IP 주소를 보유한 호스트에서 같은 기능의 서버를 IP
주소별로 따로 운용할 수 있게 함
멀티캐스팅 응용 프로그램이 같은 포트 번호를 사용할 수
있게 함
22
예제) TCPServer
4장의 TCPServer에 SO_REUSEADDR 적용
// socket()
SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
if(listen_sock == INVALID_SOCKET) err_quit("socket()");
// SO_REUSEADDR 소켓 옵션 설정
BOOL optval = TRUE;
retval = setsockopt(listen_sock, SOL_SOCKET,
SO_REUSEADDR, (char *)&optval, sizeof(optval));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
// bind()
SOCKADDR_IN serveraddr;
23
실습
예제) TCPServer
실습1
4장의 TCPServer를 2개 실행
실습2
실습8-1과 같이 SOL_REUSEADDR 옵션을 적용해서 4장의 TCPServer
코드를 변경; 변경된 TCPServer 2개 실행; TCPClient 실행과 종료를
반복하면서 서버 관찰
실습3
실습2에서 TCPServer 하나의 IP 주소는
~ s_addr = htonl(INADDR_ANY);
다른 하나는
~ s_addr = inet_addr("127.0.0.1");
로 설정 후 실행; TCPClient 실행과 종료를 반복하면서 서버 관찰
24
멀티캐스팅 (1)
멀티캐스트 주소
4비트 28비트
IPv4 1 1 1 0 그룹 ID
특징
그룹 가입과 탈퇴가 자유롭고 그룹 구성원 모두가 평등
멀티캐스트 데이터를 받으려면 그룹에 가입해야 함
멀티캐스트 데이터를 보내려고 그룹에 가입할 필요 없음
25
멀티캐스팅 (2)
멀티캐스트 데이터 전송
그룹 구성원이 데이터를 보내는 경우
A A
B B
멀티캐스트 그룹 멀티캐스트 그룹
26
멀티캐스팅 (3)
멀티캐스트 데이터 전송
그룹 비구성원이 데이터를 보내는 경우
B C
멀티캐스트 그룹
27
IPor IPV6_MULTICAST_IF 옵션 (1)
용도
IP 주소를 둘 이상 보유한 호스트에서 멀티캐스트 데이터
를 보낼 네트워크 인터페이스를 선택
사용 예
IN_ADDR localaddr;
localaddr.s_addr = inet_addr("147.46.114.70");
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&localaddr, sizeof(localaddr));
28
IPor IPV6_MULTICAST_IF 옵션 (2)
IP_MULTICAST_IF 옵션 설정 결과
응용 프로그램
147.46.114.70 147.46.115.38
29
IPor IPV6_MULTICAST_TTLor HOPS 옵션 (1)
용도
IP 헤더의 TTL(또는 Hop Limit) 값을 변경
IP 헤더 UDP 헤더 응용 프로그램 데이터
TTL
30
IPor IPV6_MULTICAST_TTLor HOPS 옵션 (2)
사용 예1
int ttl = 2;
retval = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&ttl, sizeof(ttl));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
사용 예2
int ttl = 2;
retval = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
(char *)&ttl, sizeof(ttl));
if(retval == SOCKET_ERROR) err_quit("setsockopt()");
31
IPor IPV6_MULTICAST_LOOP 옵션
용도
멀티캐스트 그룹에 가입한 응용 프로그램이 자신의 그룹
에 멀티캐스트 데이터를 보낼 때 자신도 받을지를 결정
사용 예
// 자신이 보낸 멀티캐스트 데이터는 받지 않는다.
BOOL optval = FALSE;
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&optval, sizeof(optval));
32
IPor IPV6_ADD_MEMBERSHIP,
IPor IPV6_DROP_MEMBERSHIP 옵션 (1)
용도
멀티캐스트 그룹에 가입 또는 탈퇴
옵션값
#include <ws2tcpip.h>
33
IPor IPV6_ADD_MEMBERSHIP,
IPor IPV6_DROP_MEMBERSHIP 옵션 (2)
사용 예
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("235.7.8.9");
mreq.imr_interface.s_addr = inet_addr("147.46.114.70");
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&mreq, sizeof(mreq));
34
IPor IPV6_ADD_MEMBERSHIP,
IPor IPV6_DROP_MEMBERSHIP 옵션 (3)
IP_ADD_MEMBERSHIP 옵션 설정 결과
응용 프로그램
147.46.114.70 147.46.115.38
35
예제) MuticastSender/MuticastReceiver
36
예제) MuticastSender6/MuticastReceiver6
37
TCP_NODELAY 옵션 (1)
TCP 데이터 전송 원리
데이터 1
데이터 1
윈도우 크기 = 3 데이터 2
ACK 2
데이터 3
데이터 2
ACK 4
ACK 3
데이터 4
...
38
TCP_NODELAY 옵션 (2)
용도
Nagle 알고리즘 작동 중지
(디볼트는 Nagle 알고리즘 동작)
Nagle 알고리즘
- 보낼 데이터가 MSS(maximum segment size)로 정의된
크기만큼 쌓이면, 상대편에게 무조건 보냄
- 보낼 데이터가 MSS보다 작을 경우, 이전에 보낸 데이터
에 대한 ACK가 오기를 기다림. ACK가 도달하면 보낼 데
이터가 MSS보다 작더라도 상대에게 보냄
39
TCP_NODELAY 옵션 (3)
사용 예
BOOL optval = TRUE; // Nagle 알고리즘 중지
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&optval, sizeof(optval));
40