네트워크 프로그래밍 9장 코드 정리

Hyun·2024년 12월 2일
0

01. 소켓 옵션의 종류와 관련 함수

소켓 옵션:

  1. 소켓 옵션 설정(=변경) 하기
int setsockopt(
	SOCKETS, 
    int level, // 프로토콜 코드 레벨
    int optname, // 설정할 옵션 네코드 레벨
    const char *optval // 설정 옵션 값 담는 버퍼 주소
    int optlen // 버퍼 크기
);
  1. 현재 설정된 소켓 옵션 값 얻기
int getsockopt (
	SOCKETS,
    int level,
    int optname,
    char *optval,
    int *optlen
 );

02. SOL_SOCKET 레벨 옵션

  1. SO_BROADCAST 옵션
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): 옵션의 활성화 여부

  1. SO_KEEPALIVE 옵션
DWORD bEnable = 1;
retval = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
	(const char*)&bEnable, sizeof(bEnable));
if (retval == SOCKET_ERROR err_quit("setsockopt()");
  1. SO_LINGER
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. TCPServer

else 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;
}
  1. SO_SNDBUF, SO_RCVBUF
// 수신 버퍼의 크기 얻기
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);
  1. SO_SNDTIMEO, SO_RCVTIMEO
DWORD optval = 3500;
retval = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
	(const char*)&optval, sizeof(optval));
if (retval == SOCKET_ERROR) err_quit("setsockopt()");
  1. SO_REUSEADDR
DWORD optval = 1;
retval = setsockopt(sock, SO_SOCKET, SO_REUSEADDR,
	(const char*)&optval, sizeof(optval));
if (retval == SOCK_ERROR) err_quit("setsockopt()");

03. IPPROTO_IP, IPPROTO_IPv6 레벨 옵션

  1. IP or IPv6_MULTICAST_IF
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): 데이터 크기

  1. IP or IPv6_MULTICAST_TTL or HOPS
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()");
  1. IP of IPv6_MULTICAST_LOOP
DWORD optval = 0;
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(const char*)&optval, sizeof(optval));
  1. IP or IPv6_ADD_MEMBERSHIP ,
    IP of IPv6_DROP_MEMBERSHIP
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) 멀티캐스팅 예제

  • MulticastReceiver.cpp (Broadcast -> Multicast)

#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()");
  • MulticastSender.cpp (Broadcast -> Multicast)

#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);
    
	// 멀티캐스트 데이터 보내기

04. IPPROTO_TCP 레벨 옵션

  1. TCP_NODELAY
DWORD optval = 1; 
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
	(const char*)&optval, sizeof(optval));

0개의 댓글

관련 채용 정보