2016년 6월 12일 일요일

뇌자극 TCP_IP 프로그래밍 24강 요약

24강 IPv6 프로그래밍

1. IPv4의 한계

IPv4는 0.0.0.0 ~ 255.255.255.255 로 32비트의 크기를 가진다.
대략 4억개의 장치에 유일한 IP를 할당할 수 있다.
그러다 보니 IP가 부족해서 대안으로 나온 것이 IPv6다.

2. IPv6 를 이용한 인터넷 인프라의 효과적인 활용

IP 주소 부족 문제 해결

IPv6 의 가장 큰 특징은 인터넷 주소의 크기를 기존 32비트에서 128비트로 확장했다.
거의 무한에 가까운 IP 를 할당 할 수 있다.

효율성

IPv6 는 IPv4 보다 단순한 구조의 헤더를 사용한다. 확장 헤더를 통해 기능을 쉽게 확장 시킬 수 있다.

버전 | 트래픽 클래스 | 흐름 라벨 | 패이로드 길이 | 다음 헤더 | 홉제한
                                발신자 주소
                                목적지 주소

이런식으로 생겼다.

주소 자동 설정

IPv6는 인터넷에 접속하는 순간 자동적으로 네트워크 주소를 부여 받는다.
네트워크 관리자로 부터 IP 주소를 부여 받아 수동으로 설정해야 했던 IPv4에 비하면 편하다

이동성

IPv6는 네트워크의 위치와 상관 없이 IP주소를 유지할 수 있다.

3. IPv6 환경 만들기

512비트 씩 끊어서 16진수로 표현한다.
각 자리 구분은 : 로 한다.

예) 3ffe : ffff : 0100 : f140 : 0210 : a4ff : fee3 : 9566

각 블럭의 앞자리에 오는 0은 생략해서 표현할 수 있다.

예) 3ffe : ffff : 0100 : f101 : 0 : 0 : 0 : 1 => 3ffe : ffff : 0100 : f101 : : 1

루프백 주소는  ::1 이다.

리눅스와 IPv6 

리눅스는 IPv6 주소가 부여된 상태로 부팅된다. ifconfig 로 확인할 수 있다.
할당된 IPv6 주소를 사용할 수 있는지 테스트는 ping6 명령어를 사용하면 된다.

ping6 ::1

4. IPv6 프로그램 개발

주소 체계만 다르므려 소켓을 만들고 읽고 쓰는데는 차이가 없다.
주소 체계 관련 부분만 다르다.

소켓 구현 

socket 함수를 그대로 사용한다. 소켓의 주소 영역만 AF_INET6 으로 해서 만들면 된다.

s = socket(AF_INET6, SOCK_STREAM, 0);  //TCP
s = socket(AF_INET6, SOCK_DGRAM, 0);  //UDP

소켓에 IPv6 주소를 묶어주려면 sockaddr_in6 구조체를 사용해야 한다.

#include <netinet/in.h>
struct sockaddr_in6
{
   u_int16m_t  sin6_family;    //AF_INET6
   u_int16m_t  sin6_port;    //Port 번호
   u_int32m_t  sin6_flowinfo;   //IPv6 flow information
   struct in6-addr   sin6_addr;  //IPv6 주소
   u_long   sin6_scope_id;  //이더넷 카드를 지정하기 위해 사용
}

이더넷 카드의 인덱스 값은 if_nametoindex 함수로 가져올 수 있다.
만약 eth0 의 인덱스 값을 가져오길 원한다면, 다음과 같이 하면 된다.

if_nametoindex("eth0");

IPv6 에 대응하는 bind 함수의 사용법

struct sockaddr_in6 sin6;

sin6.sin6_family = AF_INET6;
sin6.sin6_flowinfo = 0;
sin6.sin6_port = htons(3500);
sin6.sin6_addr = in6addr_any; //IPv4에서 INADDR_ANY 와 같은 의미로 사용된다.

IPv6 용 인터넷 주소 변환 함수

서버는 주소에 in6addr_any를 사용해서 모든 주소에 대해서 기다리면 되낟.
클라이언트는 서버의 IP 주소를 지정해야만 한다.
IPv6에서는 inet_addr 함수 대신에 inet_pton 함수를 이용해서 : 형식의 주소로 변환할 수 있다.

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

int inet_pton(int af, const char *src, void *dst);

매개 변수

af : 변환할 IP 프로토콜을 명시한다. IPv4 : AF_NET, IPv6 : AF_INET6 을 지정
src :  변환할 주소를 입력한다. IPv6 라면 : 로 이루어진 주소를 입력한다.
dst :  변환 결과를 반환 값으로 전달한다.

IPv6 기반 에코 서버 프로그램

socket 함수의 매개변수로 AF_INET6 를 지정하고,
struct sockaddr_in6 구조체를 사용했다는 것을 제외하고
IPv4 버전의 에코 서버와 차이가 없다.

IPv6 기반 에코 클라이언트 프로그램

IPv6 는 IPv4를 기본적으로 지원하기 때문에
하나의 소켓으로 두 개의 서로 다른 주소 체계를 모두 지원한다.

5. IPv4와 IPv6 모두를 지원하는 소켓 프로그램 개발

IPv4 와 IPv6 병행 서버 개발

소켓을 만들 때, 인터페이스의 주소 정보를 확인해서
IPv4 전용 소켓, IPv6 전용 소켓, 모두를 사용하는 소켓으로 구분하여 만들어여 한다.

getaddrinfo 함수로 소켓 주소 정보 가져오기

getaddrinfo 함수로 컴퓨터와 서비스에 대한 네트워크 소켓 주소 정보를 가져올 수 있다.

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char *node, const char *service,
                      const struct addrinfo *hints, struct addrinfo **res);
매개변수

node : 정보를 알아오기 원하는 인터넷 주소로 IPv4 주소, IPv6 주소, 호스트 이름을 지원한다.
service : /etc/services 에 포트와 대응되는 인터넷 서비스의 이름이다.
addrinfo : 가져오기 원하는 정보에 대한 힌트를 지정한다. getaddrinfo 함수는hints 값에 일치하는 네트워크 정보만 가져온다.
res : 가져온 네트워크 주소 정보는 addrinfo 구조체에 복사된다.

struct addrinfo  {
  int ai_flags;
  int ai_family;
  int ai_socktype;
  int ai_protocol;
  size_t ai_addrlen;
  struct sockaddr *ai_addr;
  char *ai_canonname;
  struct addrinfo *ai_next;
};

매개변수 

ai_flags : 추가 옵션
ai_family : AF_INET, AF_INET6 와 같은 주소 영역이다.
ai_socktype : SOCK_STREAM, SOCKDGRAM 과 같은 소켓 타입
ai_protocol : 소켓 주소 프로토콜
ai_addrlen : 주소 정보를 담고 있는 구조체 ai_addr의 크기
ai_addr : 주소 정보를 담는 구조체로 IPv4, IPv6 형식 모두를 지원한다.
ai_canonname
ai_next

AF_UNSPEC는 따로 주소지정을 하지 않겠다는 의미로 가리지 않고 주소 정보를 가져온다.

소스 코드 받기

댓글 없음:

댓글 쓰기