- getsockopt 함수의 호출방법 예제 : 프로토콜 레벨이 SOL_SOCKET이고 이름이 SO_TYPE인 옵션을 이용해서 소켓의 타입정보( TCP or UDP)를 확인하는 예제이다.
- #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
void error_handling(const char* message);
int main(int argc, char * argv[])
{
int tcp_sock, udp_sock;
int sock_type;
socklen_t optlen;
int state;
optlen = sizeof(sock_type);
tcp_sock = socket(PF_INET, SOCK_STREAM, 0); // TCP소켓을 생성한다.
udp_sock = socket(PF_INET, SOCK_DGRAM, 0); // UDP 소켓을 생성한다.
// TCP소켓 생성시 인자로 전달하는 SOCK_STREAM 상수값을 출력한다.
printf("SOCK_STREAM: %d \n", SOCK_STREAM);
// UDP 소켓 생성시 인자로 전달되는 SOCK_DGRAM 상수값을 출력하고 있다.
printf("SOCK_DGRAM: %d \n",SOCK_DGRAM);
// 소켓의 타입정보를 얻고 있다. TCP소켓이라면 SOCK_STREAM의 상수값인
// 1을 얻게 될것이다.
state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
if(state)
error_handling("getsockopt() error!");
printf("socket type one: %d \n",sock_type);
// 소켓의 타입정보를 얻고있다. UDP 소켓이라면 SOCK_DGRAM의 상수값인 2를 얻게된다.
state = getsockopt(udp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
if(state)
error_handling("getsockopt() error!");
printf("Socket type two: %d \n", sock_type);
return 0;
}
void error_handling(const char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
- 출력결과
- 위 예제를 통해서 getsockopt 함수호출을 통한 소켓정보의 확인 방법을 간단히 보였다. 참고로소켓의 타입정보 확인을 위한 옵션 SO_TYPE은 확인만 가능하고 변경이 불가능한 대표적인 옵션이다. 이는 다음의미로 받아들여진다. " 소켓의 타입은 소켓 생성시 한번 결정되면 변경이 불가능하다"
- SO_SNDBUF & SO_RCVBUF
- 소켓이 생성되면 기본적으로 입력버퍼와 출력버퍼가 생성된다. 이번에는 바로 이 입출력 버퍼와 관련있는 소켓옵션에 대해 소개한다.
- SO_RCVBUF는 입력버퍼의 크기와 관련된 옵션이고 SO_SNDBUF는 출력버퍼의 크기와 관련된 옵션이다. 즉 이 두옵션을 이용해서 입출력 버퍼의 크기를 참조 할 수있고 변경도 가능하다.
- get_buf.c 예제
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
void error_handling(const char* message);
int main(int argc, char *argv[])
{
int sock;
int snd_buf, rcv_buf, state;
socklen_t len;
sock = socket(PF_INET, SOCK_STREAM, 0);
len = sizeof(snd_buf);
state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
if(state)
error_handling("getsockopt() error!");
len = sizeof(rcv_buf);
state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, &len);
if(state)
error_handling("getsockopt() error!");
printf("Input buffer size: %d \n", rcv_buf);
printf("Output buffer size: %d \n", snd_buf);
return 0;
}
void error_handling(const char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
- 출력결과
- 위의 실행결과는 실행하는 환경에 따라서 많은 차이가 날 수도 있다.
- 이번에는 입출력 버퍼의 크기를 임의로 변경해보자
- set_buf.c 예제
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
void error_handling(const char* message);
int main(int argc, char *argv[])
{
int sock;
int snd_buf = 1024*3, rcv_buf = 1024*3;
int state;
socklen_t len;
sock = socket(PF_INET, SOCK_STREAM, 0);
state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf, sizeof(rcv_buf));
if(state)
error_handling("setsockopt() error!");
state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, sizeof(snd_buf));
if(state)
error_handling("setsockopt() error!");
len = sizeof(snd_buf);
state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf, &len);
if(state)
error_handling("getsockopt() error!");
len = sizeof(rcv_buf);
state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*) &rcv_buf, &len);
if(state)
error_handling("getsockopt() error!");
printf("Input buffer size : %d \n",rcv_buf);
printf("Output buffer size : %d \n ", snd_buf);
return 0;
}
void error_handling(const char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
- 출력결과
- 출력 결과에서는 우리의 기대와 전혀 다른 결과를 보이고 있다. 그런데 이런 결과를 보이는 데는 그만한 이유가 있다. 입출력 버퍼는 상당히 주의 깊게 다뤄져야 하는 영역이다 때문에 우리의 요구대로 버퍼의 크기가 정확히 맞춰지지 않는다.
- 다만 우리는 setsockopt함수호출을 통해서 버퍼의 크기에 대한 우리의 요구사항을 전달할 뿐이다. 만약 우리가 출력버퍼의 크기를 0으로 변경하려는 경우 이를 그대로 반영한다면 TCP 프로토콜진행에서 흐름제어와 오류 발생시의 데이터 재전송과 같은일을 할수없다. 그럼으로 최소한의 버퍼를 가지고 있다. 그렇기 때문에 100% 우리의 요구대로 버퍼의 크기가 만들어지지는 않는다. 다만 대략적으로 버퍼의 크기가 반영되었음을 알수는 있다.
'책 > 윤성우 TCPIP' 카테고리의 다른 글
09-2 : SO_REUSEADDR (2) (0) | 2020.12.13 |
---|---|
09-2 : SO_REUSEADDR (0) | 2020.12.12 |
09-1 소켓의 옵션과 입출력 버퍼의 크기 (0) | 2020.12.10 |
chapter 08 -2 , ip주소와 도메인 이름 사이의 변환 (3) (0) | 2020.12.09 |
< 08-2 : IP 주소와 도메인 이름 사이의 변환 예제 > (0) | 2020.12.08 |