Coding Memo
Socket Option - (get/set)sockopt() 본문
본 포스팅은 인프런에 등록되어 있는 Rockiss 님의 강의를 보고 간단하게 정리한 글입니다.
socket을 만들고 이 소켓에 대한 여러가지 세팅을 해줄 수 있다.
다음의 함수를 이용한다.
setsockopt()
int setsockopt(
[in] SOCKET s,
[in] int level,
[in] int optname,
[in] const char *optval,
[in] int optlen
);
SOCKET | s | 설정을 할 타켓 소켓 |
int | level | 옵션이 정의될 레벨 (SOL_SOCKET 이용) |
int | optname | 설정할 옵션 이름 |
const char* | optival | 설정할 옵션의 값 |
int | optlen | 설정할 옵션의 값의 크기 |
char*로 옵션의 값을 받는 이유는 옵션에 대한 값을 여러가지 타입으로 받기 위해서이다. (따라서 길이도 필요하다.)
자세한 내용은 다음의 문서에 나와있다.
https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-setsockopt
참고로 set 목적이 아닌 단순 get 목적인 경우에는 getsockopt()라는 함수도 있다.
int getsockopt(
[in] SOCKET s,
[in] int level,
[in] int optname,
[out] char *optval,
[in, out] int *optlen
);
SOCKET | s | 설정을 확인할 소켓 |
int | level | 옵션이 정의된 레벨 |
int | optname | 확인할 옵션이름 |
char [out] | optival | 확인할 옵션의 값 할당 |
int [out] | optlen | 확인할 옵션의 값의 크기 할당 |
level은 옵션을 해석하고 처리할 주체로
소켓 코드 : SOL_SOCKET
IPv4 : IPPROTO_IP
TCP Protocol: IPPTORO_TCP
등을 사용할 수 있다.
setsockopt, getsockopt 두 함수 모두 에러 없이 처리가 되었다면 0을 반환한다.
문서를 보면 여러가지 옵션들이 나와있는데 그 중 몇 개만 알아보자.
1. SO_KEEPALIVE
TCP 연결에서 주기적으로 연결 상태를 확인할지를 결정하는 옵션이다.
만약 상대방이 갑작스럽게 연결을 끊을 수도 있는 상황이 발생할 수도 있기 때문에, 이 옵션으로 주기적으로 TCP 프로토콜 연결 상태를 확인하여 끊어진 연결을 감지해 낼 수 있다. (SOL_SOCKET)
값: 0 or 1 [bool]
bool enable = true;
::setsockopt(serverSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&enable, sizeof(enable));
2. SO_LINGER
socket이 closed 되었을 때, 송신 버퍼에 남아있는 데이터를 보낼 것인지 아니면 버릴 것인지를 결정하는 옵션이다.
send를 호출 한 직후에 바로 closesocket으로 소켓을 바로 닫아버렸을 때, socket은 닫힌 상태이므로 send가 되지 못한다. 이를 방지하기 위해서 송신 버퍼에 남아있는 데이터를 보낼 수 있도록 지연 시간을 지정해줄 수 있다.
l_linger 값만큼 지연하여 l_linger 초 만큼 대기 후 (데이터를 보낼 시간을 주고) 소켓을 닫게 된다. (SOL_SOCKET)
(l_linger 기본값은 0이다.)
값: LINGER (l_onoff: 사용 여부, l_linger: 대기 시간)
struct linger {
u_short l_onoff; /* option on/off */
u_short l_linger; /* linger time */
};
LINGER linger;
linger.l_onoff = 1; // true
linger.l_linger = 5; // 대기 시간
::setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));
참고: shutdown 함수로 socket을 완전히 닫지 않고 send/recv를 각각 허용하거나 닫을 수 있다.
closesocket을 바로 하지 말고 상대방이 계속 데이터를 보낼 수도 있으니 이 함수를 이용하는 것도 linger를 사용하는 방법과 비슷하다.
SD_SEND: send만 막음
SD_RECIEVE: recv만 막음
SD_BOTH: 둘 다 막음
::shutdown(serverSocket, SD_SEND);
3. SO_SNDBUF / SO_RCVBUF
소켓의 SendBuffer의 크기와 ReceiveBuffer의 크기를 지정할 수 있다.
또한, getsockopt로 기본 설정되어 있는 크기를 출력해 보면 둘다 65536 bytes (64Kb)인 것을 알 수 있다. (SOL_SOCKET)
값: int
int sendBufferSize;
int optionLen = sizeof(sendBufferSize);
::getsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sendBufferSize, &optionLen);
// default: 65536 bytes (64KB)
int recvBufferSize;
optionLen = sizeof(recvBufferSize);
::getsockopt(serverSocket, SOL_SOCKET, SO_RCVBUF, (char*)&recvBufferSize, &optionLen);
// default: 65536 bytes (64KB)
4. SO_REUSEADDR
IP 주소와 port를 재사용 할 수 있도록 하는 옵션이다.
어떤 프로그램이 종료된 후에 그 프로그램에서 bind 되어있는 소켓의 포트의 점유가 바로 풀리는 것이 아닌 잠시동안 계속 점유하고 있을 때가 있는데, 이 상황에서 그 포트를 사용하고 싶다면 이 옵션을 이용하면 된다.
(만약 이미 bind 되어 있는 포트로 다시 bind를 하려고하면 에러가 날 것이다.)
사용하는 것이 편하다! (SOL_SOCKET)
값: 0/1 [bool]
bool enable = true;
::setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&enable, sizeof(enable));
5. TCP_NODELAY
Nagle 알고리즘 작동 여부에 관한 옵션이다.
데이터가 충분히 크면 보내고, 그렇지 않으면 데이터가 충분히 쌓일때 까지 대기 후, 쌓인 후에 패킷을 보내는 알고리즘이다.
작은 패킷이 불필요하게 많이 생성되고 전송되는 일을 막을 수 있지만, 바로바로 전송되지 않기 때문에 반응 시간에 손해가 있다. (따라서 반응시간이 중요한 게임에서는 일반적으로 잘 사용되지 않는다.)
* level 지정 시 IPPROTO_TCP로 해야한다.
값: 0/1 [bool]
bool enable = true;
::setsockopt(serverSocket, IPPROTO_TCP, TCP_NODELAY, (char*)enable, sizeof(enable));
6. SO_RCVTIMEO / SO_SNDTIMEO
send 한거나 recv할 시 blocking 되는 시간을 지정 할 수있다. (단위: milliseconds)
지정된 시간이 지나면 send나 recv함수는 -1를 반환한다.
값: DWORD (window에서 unsinged long)
unsigned long t = 10000;
::setsockopt(serverSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&t, sizeof(t));
unsigned long tt;
int tts = sizeof(tt);
getsockopt(serverSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&tt, &tts);
cout << tt << " " << tts << endl;
'Game Server (C++)' 카테고리의 다른 글
Socket IO - Select (0) | 2022.11.18 |
---|---|
Non-blocking Socket (0) | 2022.11.18 |
Socket Programming - UDP (0) | 2022.11.03 |
Socket Programming - TCP (0) | 2022.10.31 |
Socket Programming Basic (0) | 2022.10.18 |