socket의 옵션과 입출력 버퍼의 크기
- socket의 다양한 옵션

- IPPROTO_IP: IP 프로토콜에 관련된 사항
- IPPROTP_TCP: TCP 프로트콜에 관련된 사항
- SOL_SOCKET: socket에 대한 가장 일반적인 옵션
(socket의 타입: SO_TYPE은 socket 생성 시 한번 결정되면 변경이 불가하다)
- socket의 옵션 변경 방법
- getsockopt & setsockopt
int getsockopt(
[in] SOCKET s, // 옵션확인을 위한 socket의 file descriptor 전달
[in] int level, // 확인할 옵션의 프로토콜 레벨 전달
[in] int optname, // 확인할 옵션의 이름 전달
[out] char *optval, // 확인 결과의 저장을 위한 버퍼의 주소값 전달
[in, out] int *optlen // optval로 전달된 주소값의 버퍼크기를 담고 있는 변수의 주소값
);
→ 성공 시 0, 실패 시 -1 반환
int setsockopt(
[in] SOCKET s, // 옵션변경을 위한 socket의 file descriptor
[in] int level, // 변경할 옵션의 프로토콜 레벨
[in] int optname, // 변경할 옵션의 이름
[in] const char *optval, // 변경할 옵션정보를 저장한 버퍼의 주소값
[in] int optlen // optval의 바이트 단위 크기
);
→ 성공 시 0, 실패 시 -1 반환
// check type of socket
int main()
{
SOCKET tcp_sock, idp_sock;
int sock_type;
int sock_len;
int state;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock_len = sizeof(sock_type);
tcp_sock = socket(PF_INET, SOCK_STREAM, 0);
idp_sock = socket(PF_INET, SOCK_DGRAM, 0);
printf("SOCK_STREAM: %d\n", SOCK_STREAM);
printf("SOCK_DGRAM: %d\n", SOCK_DGRAM);
state = getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &sock_len);
if (state == -1)
err_handling("getsockopt() error");
printf("tcp_sock: %d\n", sock_type);
state = getsockopt(idp_sock, SOL_SOCKET, SO_TYPE, &sock_type, &sock_len);
if (state == -1)
err_handling("getsockopt() error");
printf("idp_sock: %d\n", sock_type);
WSACleanup();
return 0;
}
// 실행 창
SOCK_STREAM: 1
SOCK_DGRAM: 2
tcp_sock: 1
idp_sock: 2
- SO_SNDBUF & SO_RCVBUF
: 입출력 버퍼 관련 (SO_RCVBUF: 입력버퍼의 크기와 관련, SO_SNDBUF: 출력버퍼의 크기와 관련)
// 입출력 버퍼의 크기 확인
int main()
{
SOCKET sock;
int send_buf, recv_buf;
int len;
int state;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
err_handling("socket() error");
// 출력버퍼의 크기
len = sizeof(send_buf);
state=getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &send_buf, &len);
if (state == -1)
err_handling("getsockopt() error");
printf("send buff:%d\n", send_buf);
len = sizeof(recv_buf);
state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recv_buf, &len);
if (state == -1)
err_handling("getsockopt() error");
printf("receive buff:%d\n", recv_buf);
WSACleanup();
return 0;
}
// 실행 창
send buff:65536
receive buff:65536
// 입출력 버퍼의 크기 변경
// 입출력 크기 변경
int main()
{
SOCKET sock;
int sen_buf = 1024 * 3, rcv_buf = 1024 * 3;
int len, state;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
err_handling("startup() error");
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
err_handling("socket() error");
// 출력버퍼의 크기 변경
len = sizeof(sen_buf);
state = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sen_buf, &len);
if (state == -1)
err_handling("setsockopt() error");
// 입력버퍼의 크기 변경
len = sizeof(rcv_buf);
state = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcv_buf, &len);
if (state == -1)
err_handling("setsockopt() error");
len = sizeof(sen_buf);
state = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sen_buf, &len);
if (state == -1)
err_handling("getsockopt() error");
len = sizeof(rcv_buf);
state = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcv_buf, &len);
if (state == -1)
err_handling("getsockopt() error");
printf("sen_buf: %d\n", sen_buf);
printf("rcv_buf: %d\n", rcv_buf);
WSACleanup();
return 0;
}
// 실행 창
sen_buf: 3072
rcv_buf: 3072
- SO_SNDBUF & SO_RCVBUF를 통해서 입출력 버퍼의 크기를 변경한다 할지라도 버퍼의 크기는 정확히 맞춰지지 않음
(흐름제어, 오류 발생시의 데이터 재전송 같은 일을 위해 최소한의 버퍼 필요)