1절. 소개
2번 정도의 IPv6 관련 기사를 통해서, IPv6 의 기본적인 특성과 리눅스 상에서 IPv6 환경을 만들기
위한 방법에 대해서 알아보았다.
이번 강좌는 여러분이 IPv6 에 대한 기초적인 지식을 가지고 있으며, 리눅스 상에 IPv6 환경을
만들수 있다는 가정하에, 실질적인 IPv6 프로그래밍 과정에 대해서 알아보도록 할것이다.
IPv6의 개념과 리눅스상에서의 IPv6 환경구축에 대한 내용을 아직 모르고 있다면 IPv6(1)
- 개요 와 IPv6(2) - 환경설정 문서를 먼저 읽어 보기 바란다.
또한 이 강좌는 여러분이 Socket API에 대한 기본적인 이해를 하고 있다는 가정하에 이루어질것이다.
2절. IPv6 Socket 프로그래밍
여기에서는 IPv6 를 위한 소켓지원사항과 관련 구조체 정보와 IPv6 를 다루기 위한 기본적인
API 에 대해서 알아볼것이다.
여기에 있는글은 Linux Kernel 2.4.x 상에서 테스트 되었다.
2.1절. 변경사항들
2.1.1절. 확장된 API들
나중에 예제를 보면 알겠지만 IPv4, IPv6 모두 기본적인 프로그래밍 방법은 완전히 동일하다. IPv6 는 128비트 주소체계를 가지며, 이를 지원하기 위해서 기존의 IPv4 의 주소 구조체와는 사실 IPv4가 가지는 sockaddr_in 구조체의 경우 8byte 의 여유 저장공간을 가지고 있기는 하다. 인터넷주소/이름 간 변환을 위해서 보통 gethostbyname()과 gethostbyaddr() 함수를 사용한다. Linux 2.4.x 에서의 경우 Ipv6 에도 사용가능하도록 확장 되어있다. inet_ntoa()와 inet_addr() 같은 함수들인데, IPv4 주소를 binary 와 printable 간 변경을 위해서 이들내용은 2.2.2절를 참조하기 바란다. 이 외에도 IPv6 의 추가된 몇가지 기능들을 제공하기 위해서 소켓옵션관련 함수들을 비롯해서
다만 IPv6 의 경우 IP 주소체계의 변환과 그에 따른 몇가지 다른 API 들이 제공되는 정도에 차이가
있을 뿐이다.
다르게 구성된다. 이 주소 구조체는 보통 "sockaddr_in" 이라는 이름의 구조체로 작성되며,
각종 소켓함수에서 사용되어진다. 이러한 소켓함수들의 경우 IPv4 와 IPv6 간 차이는 없으나,
주소구조체의 경우 차이를 가지게 된다. IPv6 의 경우 sockaddr_in6 라는 새로운 구조체를
사용하게 된다.
그러나 128 bit 크기의 IPv6 타입의 주소를 저장하기에는 너무 작은 공간이다.
최소한 16byte 의 크기를 지정할수 있어야 하는데, 그런이유로 기존의 sockaddr_in 구조체를
확장해서 사용하지 못하고, 전혀 새로운 소켓구조체를 만들게 된것이다.
아마도 처음에 IPv4 프로토콜을 만들때 32 bit 면 충분할것으로 생각했기 때문일것이다.
보통 이함수들은 IPv4와 IPv6 모두를 지원하지만, 지원하지 않는 OS가 있을수도 있음으로
반드시 man page 등을 통해서 확인해 주어야 한다.
사용된다. 이 함수들은 32bit IPv4 주소에 사용가능하도록 만들어 졌으며, 당연히 128bit IPv6 에는
사용이 불가능하다. 그런 이유로 새로운 API를 제공한다.
몇가지 추가된 것들이 있다.
2.1.2절. IPv6 관련 구조체
아마도 이글을 읽고 있는 여러분은 분명 IPv4 기반하에서의 소켓 프로그래밍에 대해서는 매우
능숙하리라. IPv4 관련 소켓 프로그래밍에서 우리는 IPv4 정보를 효과적으로 저장하기 위한
여러가지 구조체를 다루었었다.
여러분이 다루었던 IPv4 관련 구조체는 소켓연결 정보를 위해서 사용되는 sockaddr_in 구조체와
소켓주소 정보를 위해서 사용되는 in_addr구조체 이다.
#include <netinet/in.h> |
IPv6 는 sockaddr_in6 라는 별도의 구조체를 제공한다.
#include <netinet/in.h> |
2.2절. IPv6 지원을 위한 소켓 API
2.2.1절. 소켓 생성/연결관련 API
API 에서 제공하는 기본적인 소켓함수들인 socket, bind, connect, sendmsg, accept 등은
IPv6 에서 그대로 사용가능하다. 다만 프로토콜지원사항과, 사용되는 구조체에 있어서 약간의
차이가 있을 뿐이다.
2.2.1.1절. socket()
endpoint 소켓 지시자를 만들기 위해서 사용하는 socket() 함수의 경우 IPv4/TCP 소켓을
만들고자 할경우 다음과 같이 사용할것이다.
s = socket(PF_INET, SOCK_STREAM, 0); |
s = socket(PF_INET, SOCK_DGRAM, 0); |
s = socket(PF_INET6, SOCK_STREAM, 0); |
한번 컴파일후 테스트 해보기 바란다.
예제 : ipv6_socket.c
#include <sys/types.h> |
올리지 않았기 때문이다.
[root@localhost c_source]# ./ipv6_socket |
modprobe 명령어를 이용해서 아래와 같은 방법으로 적재시킬수 있다.
[root@localhost c_source]# modprobe ipv6 |
2.2.1.2절. bind()
bind 는 socket() 를 이용해서 생성된 endpoint 에 포트번호, 주소와 같은 소켓특성을 묶어주기
위해서 사용되며, 다음과 같은 방식으로 사용가능하다. 또한 사용하는 구조체에 있어서도 IPv4 와
차이가 있는데, IPv4용 구조체인 sockaddr_in 대신에 IPv6 에서 사용가능한 sockaddr_in6
구조체를 사용하게 된다.
struct sockaddr_in6 sin6; |
2.2.2절. 주소변환관련 API
ipv4 에서는 문자열의 인터넷주소를 32bit 이진 데이타 주소로 변환하기 위해서 inet_addr 을,
그반대로 32bit 이진 데이타 주소를 문자열의 인터넷주소로 변환하기 위해서 inet_ntoa 함수를
사용했었다.
이들 함수는 기본적으로 32bit 인터넷 주소에 최적화 된값들이기 때문에 128비트 주소체계를
가지는 IPv6 주소의 변환을 위해서는 사용할수 없도록 만들어져 있다.
때문에 Socket API 에서는 이들변환이 가능하도록 하기 위한 별도의 함수를 제공한다. 문자열의
IPv6 인터넷주소를 128bit 이진데이타 주소로 변경하기 위해서 inet_pton 그 반대의 변경을
위해서 inet_ntop 를 제공하는데, 이들 함수의 자세한 사용방법에 대해서 알아보도록 하겠다.
2.2.2.1절. inet_pton
IPv6 문자열 인터넷 주소를 128 비트 이진데이타 주소로 변경하기 위해서 사용되는 함수이다.
이함수는 IPv6 에만 특화된 함수는 아니며, 프로토콜 범용으로 사용할수 있도록 inet_addr 함수를
확장시킨것으로 IPv4 와 IPv6 모두의 주소변환에 사용할수 있도록 범용화 되어 있다.
다음은 함수 선언이다.
#include <sys/types.h> |
가르키는 인터넷 문자열을 프로토콜종류에 맞도록 이진데이타로 변경해서 dst로 복사한다.
만약 잘못된 주소이름을 변경하고자 할경우에는 0이 리턴된다.
2.2.2.2절. inet_ntop
inet_pton 과 반대의 일을 한다. 즉 128비트 이진데이타 주소를 문자열 인터넷 주소로 변경한다.
이함수 역시 IPv6 전용의 함수는 아니며 프로토콜 범용으로 사용할수 있도록 inet_ntoa 를 확장한
함수이다.
const char *inet_ntop(int af, const void *src, char *dst, size_t cnt); |
2.2.2.3절. 주소변경 예제
다음은 inet_pton 과 Inet_ntop 를 이용한 간단한 주소변경 예제이다.
예제 : addr_cp.c
#include <sys/types.h> |
2.3절. ipv6 네트웍 프로그래밍 예제
일단 IPv6 소켓을 만들고 연결하기 위한 기본적인 API 에 대해서 알아봤음으로 기본적인 IPv6
기반의 네트웍 프로그래밍이 가능한 상태이다. 이제 실제 IPv6 기반의 서버/클라이언트
어플리케이션을 제작해서 제대로 작동하는지 확인해보도록 하겠다.
작성하고자 하는 어플리케이션은 echo 서버와 클라이언트이다. 이미 몇번에 걸쳐서 ipv4 버젼용으로
코드를 만들어본적이 있음으로, 작동방식에 대해서는 설명하지 않도록 하겠다.
테스트를 하기전에 먼저 IPv6 환경을 만들어줘야 하는데, ifconfig 를 이용해서 수동으로 IPv6 번호를
할당하였다. IP 번호는 3ffe:ffff:0:f101::1/128 로 세팅했다. ifconfig 를 통한 IPv6 할당에 관한 내용은
IPv6(2) - 환경설정 문서를 참고하기 바란다.
다음은 필자의 네트웍환경을 ifconifg 를 통해서 확인한 결과이다.
eth0 Link encap:Ethernet HWaddr 00:50:BF:2C:7B:B2 |
아래의 예제들을 보면 알겠지만 IPv6 기반의 네트웍 플밍도 방법론적인 관점에서 보자면,
기본적으로 IPv4 와 완전동일하며 쉽게 작성가능하다는걸 알수 있을것이다.
2.3.1절. echo 서버
우선 서버측 프로그램을 만들어 보도록 하자. 에러처리등은 신경쓰지 않고 구현에만 신경을 썼다.
예제 echo6_s.c
#include <sys/types.h> |
외에는 IPv4 버젼의 echo 서버와 별차이를 느낄수 없을 것이다.
2.3.2절. echo 클라이언트
이번에는 클라이언트측 프로그램이다. 서버프로그램과 마찬가지로 매우간단하다.
예제 : echo_c.c
#include <sys/types.h> |
위의 서버클라이언트가 실행된 상태에서 netstat 를 이용 해서 네트웍 연결상황을 살펴보면 아래와
같은 상태확인이 가능할것이다.
[root@localhost test]# netstate -a |
3절. 결론
이상 간단하게 IPv6 기반의네트웍 프로그래밍 기법에 대해서 알아보았다. 이문서에서는 모든 것을
설명하고 있지는 않으며, IPv6 네트웍 프로그래밍을 위한 가장 기본이 되는 내용들만 다루고 있다.
더 깊이 들어가기 원한다면 각자 관련자료를 찾아서 공부를 해야할것이다.
후에 라도 몇가지 빠진 API 들과, IPv6 에서 확장된 다른 기능을 다루는 방법에 대한 내용을
추가할것을 약속한다
작성자 : 윤 상배
작성일 : 2003년 3월 19일 23시
http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/IPv6_Programing
관련 RFC
RFC 3493, Basic Socket Interface Extensions for IPv6
RFC 3542, Advanced Sockets Application Program Interface (API) for IPv6
RFC2553, IPv6 socket APIs

Comments List
洹몃
以