int setsockopt(
SOCKETS,
int level, // 프로토콜 코드 레벨
int optname, // 설정할 옵션 네코드 레벨
const char *optval // 설정 옵션 값 담는 버퍼 주소
int optlen // 버퍼 크기
);
int getsockopt (
SOCKETS,
int level,
int optname,
char *optval,
int *optlen
);
DWORD bEnable = 1;
retval = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
(const char*)&bEnable, sizeof(bEnable));
if (retval == SOCKET_ERROR) err_quit("setsockopt()"));
sock: 설정할 소켓 핸들
SQL_SOCKET: 소켓 레벨에서 옵션 설정
SO_BROADCAST: 브로드캐스트 옵션 활성화
(const char*)&bEnable: 옵션 값 (1 = 활성화, 0 = 비활성화)
sizeof(bEnable): 옵션 값의 크기
bEnable(Broadcast Enable): 옵션의 활성화 여부
DWORD bEnable = 1;
retval = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
(const char*)&bEnable, sizeof(bEnable));
if (retval == SOCKET_ERROR err_quit("setsockopt()");
struct linger {
u_short l_onoff; // 0=off, nonzero=on
u_short l_linger; // linger time(seconds)
}
struct linger optval;
optval.l_onoff = 1;
optval.l_linger = 10;
retval = setsockopt(sock, SOL_SOCKET, SO_LINGER.
(const char*)&optval, sizeof(optval));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
shutdown() 함수
1. TCPServerelse if (retval == 0) { // 클라이언트가 송신 종료 시, 알림 메시지를 보내고 연결 종료 const char* close_msg = "Connection Closed"; send(client_sock, close_msg, strlen(close_msg), 0); printf("[TCP 서버] 클라이언트 송신 종료. 연결 종료 메시지를 보냈습니다.\n"); break; }
2.TCPClient
// 빈 문자열인 경우 송신 종료 후 서버의 응답을 한 번 받고 종료 if (strlen(buf) == 0) { shutdown(sock, SD_SEND); // 송신 종료 printf("[TCP 클라이언트] 송신을 종료하고 서버의 응답을 기다립니다.\n"); // 서버의 응답 받기 retval = recv(sock, buf, BUFSIZE, 0); if (retval > 0) { buf[retval] = '\0'; printf("[TCP 클라이언트] 서버의 마지막 응답: %s\n", buf); } break; }
// 수신 버퍼의 크기 얻기
DWORD optval; int optlen;
optlen = sizeof(optval); // optval = 수신 버퍼 크기, optlen = optval 변수의 크기 저장
retval = getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF,
(char*)optval, &optlen);
if (retval == SOCKET_ERROR) err_quit("getsocketopt()")
printf("수신 버퍼 크기(old) = %d바이트\n", optval);
// 수신 버퍼의 크기 두 배 늘리기
optval *= 2;
retval = setsocketopt(listen_sock, SOL-SOCKET, SO_RCVBUF,
(const char*)&optval, sizeof(optval));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
// 수신 버퍼의 크기를 얻기
optlen = sizeof(optval);
retval = getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF,
(const char*)&optval, &optlen)
if (retval == SOCKET_ERROR) err_quit("getsockopt()");
printf("수신 버퍼 크기(new) = %d바이트\n", optval);
DWORD optval = 3500;
retval = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
(const char*)&optval, sizeof(optval));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
DWORD optval = 1;
retval = setsockopt(sock, SO_SOCKET, SO_REUSEADDR,
(const char*)&optval, sizeof(optval));
if (retval == SOCK_ERROR) err_quit("setsockopt()");
DWORD localaddr;
inet_pton(AF_INET, "147.46.114.70", &localaddr);
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
(const char*)&localaddr, sizeof(localaddr));
AF_INET: IPv4 주소 체계 사용
"147.46.114.70": 사용할 네트워크 인터페이스의 IP 주소
&localaddr: 변환된 이진 데이터를 저장할 변수
sock: 옵션 설정할 소켓
IPPROTO_IP: IP 프로토콜 수준의 옵션
IP_MULTICAST_IF: 멀티캐스트 송신 인터페이스
(const char*)&localaddr: 인터페이스 IP 주소를 저장한 데이터
sizeof(localaddr): 데이터 크기
DWORD ttl = 2;
retval = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
(const char*)&ttl, sizeof(ttl));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
DWIRD ttl = 2;
retval = setsockopt(sock, IPPROTO_IPv6, IPv6_MULTICAST_HOPS,
(const char*)&ttl, sizeof(ttl));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
DWORD optval = 0;
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(const char*)&optval, sizeof(optval));
stuct ip_mreq {
struct in_addr imr_multiaddr; // Ipv4 멀티캐스트 주소
struct in_addr imr_interface; // 로컬 인터페이스의 Ipv4 주소 (기본 0)
}
struct ipv6_mreq {
struct in6_addr ipv6mr_multiaddr; // Ipv6 멀티캐스트 주소
struct int ipv6mr_interface // 로컬 인터페이스의 인덱스 (기본 0)
};
사용 예시
struct ip_mreq mreq; // 147.46.114.70 주소의 인터페이스를 멀티캐스트 그룹 235.7.8.9에 가입
inet_pton(AF_INET, "235.7.8.9", &mreq.imr_multiaddr);
inet_pton(AF_INET, "147.46.114.70", &mreq.imr_interface);
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char*)&mreq, sizeof(mreq));
MulticastReceiver 에서 멀티캐스트 그룹에 가입하고 탈퇴하는 코드
#define MULTICASTIP "235.7.8.9"
// 멀티캐스트 그룹 가입
struct ip_mreq mreq;
inet_pton(AF_INET, MULTICASTIP, &mreq.imr_multiaddr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
retval = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMEBERSHIP,
(const char*)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
// 멀티캐스트 그룹 탈퇴
retval = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(const char*)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
MulticastReceiver6에서 멀티캐스트 그룹에 가입하고 탈퇴하는 코드
#define MULTICASTIP "FF12::1:2:3:4"
// 멀티캐스트 그룹 가입
struct ipv6_mreq mreq;
inet_pton(AF_INET6, MULTICASTIP, &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = 0;
retval = setsockopt(sock, IPPROTO_IPV6, IP_JOIN_GROUP,
(const char*)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
// 멀티캐스트 그룹 탈퇴
retval = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
(const char*)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
실습 9-2 (IPv4) 멀티캐스팅 예제
#define MULTICASTIP "235.7.8.9"
#define LOCALPORT 9000
#define BUFSIZE 512
// SO_REUSEADDR 옵션 설정
DWORD optval = 1;
retval = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&optval, sizeof(optval));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
// 멀티캐스트 그룹 가입
struct ip_mreq mreq;
inet_pton(AF_INET, MULTICASTIP, &mreq.imr_multiaddr);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
retval = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(const char *)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
// 멀티캐스트 데이터 받기
// 멀티캐스트 그룹 탈퇴
retval = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(const char *)&mreq, sizeof(mreq));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
#define MULTICASTIP "235.7.8.9"
#define REMOTEPORT 9000
#define BUFSIZE 512
// 멀티캐스트 TTL 설정
DWORD ttl = 2;
retval = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
(const char *)&ttl, sizeof(ttl));
inet_pton(AF_INET, MULTICASTIP, &remoteaddr.sin_addr);
// 멀티캐스트 데이터 보내기
DWORD optval = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(const char*)&optval, sizeof(optval));