• 검색 결과가 없습니다.

TCP/IP 소켓 프로그래밍 C 2판

N/A
N/A
Protected

Academic year: 2023

Share "TCP/IP 소켓 프로그래밍 C 2판"

Copied!
16
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

목포해양대 해양전자통신공학부

얇지만 얇지 않은

TCP/IP 소켓 프로그래밍 C 2판

Chap 3. Of Names and Address Families

(2)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

Chap. 3 Of Names and Address Families

3.1 도메인 네임 주소를 숫자 주소로 매핑하기

3.2 IP 버젂에 무관한 주소-범용 코드의 작성

3.3 숫자 주소에서 도메인 네임 주소 획득하기

(3)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

기존 IPv4전용, IPv6전용 코드의 취약성

전용주소 코드(IPv4 only, IPv6 only)의 의미

 IPv4 젂용 코드는 IPv4 형식의 IPv4만 취하고 IPv6 젂용 코드는 IPv6 주소 형식만 취한다.

 상대방의 IP 주소 버젂을 모를 경우, 두 가지 버젂을 모두 준비해야 함

IPv4, IPv6 범용 코드

 실행 시갂에 주소 버젂을 확인하여 IPv4, IPv6 주소 타입에 관계없이 동작하게 하는 코드

 내부적으로는 이름-주소 변홖 함수인 getaddrinfo() 함수를 사용하여 동작

getaddrinfo()는 /etc/hosts, DNS 시스템에 질의하여 가능한 모듞 IPv4(A record), IPv6(AAAA record) 주소를 리스트화 하여 반홖

이름 주소-> IP주소로 변홖하는 네임 시스템 API

 하나의 코드로 IPv4, IPv6에 모두 대비

(4)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

도메인 네임 시스템

도메인 네임 시스템(Domain Name System)이란?

 인터넷에서 호스트를 구분하기 위하여 IP 대싞 네임(이름 주소)을 사용할 수 있도록 하는 서비스

 네임주소 - IP 주소를 매핑하는 DB를 홗용하여 서비스

로컬 DB 홗용 : /etc/host(linux) or

windows/system32/dirvers/etc/hosts(windows)

분산 DB 홗용 : DNS(domain Name Service)

(5)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

도메인 네임 시스템

장점

 읽기, 쓰기, 기억의 편의성

인터넷에서 호스트는 IP 주소로 구분이 가능

숫자 형태보다, 계층화된 이름 주소가 더 좋은 사용 편의성을 제공

 고정된 주소 값 제공

IP 주소는 특성상 위치 이동 시 변경되나 네임 주소는 이를 클라이얶트에 숨겨주어 다른 사람에게 항상 같은 주소를 제공한다

 부하 분배(load balancing)

하나의 네임주소에 여러 개의 IP 주소 매핑이 가능하며 결과적으로 서로 다른 물리적인 서버가 클라이얶트의 요청에 대응하게 할 수 있다

특징

 DNS가 TCP/IP 프로그래밍의 필수요소는 아님

(6)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

IPv4, IPv6 통합 네임 서비스 API

기능 : 프로토콜 버전에 상관없이 네임 주소 -> IP 주소 해석을 해주는 함수

 호스트 주소(IP 혹은 도메인 네임)와 서비스(서비스 이름 혹은 port 번호)을 젂달하면 위 정보에 연결가능한 주소

정보(addrinfo) 리스트를 반홖한다

 호스트 연결 시 도메인 네임, IPv4 주소, IPv6 주소를 모두 사용가능

hostStr: 네임 주소 혹은 IP 주소

serviceStr: 서비스 이름 혹은 port 번호

hints: 반홖을 원하는 주소 정보의 형태

IPv4 및 IPv6 선택, 프로토콜 종류 등의 선택이 가능

results: 반홖되는 주소들의 결과 리스트

int getaddrinfo (const char *hostStr, const char *serviceStr,

const struct addrinfo *hints, struct addrinfo **results)

(7)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

IPv4, IPv6 통합 네임 서비스 API

struct addrinfo{

int ai_flags;//

제어 정보 해설을 위한

flag

int ai_family;//Family:AF_INET,AF_INET6,AF_UNSPEC

int ai_socktype;//Socket type:SOCK_STREAM,SOCK_DGRAM int ai_protocol;//Protocol:0(default)or IPPROTO_XXX

socklen_t ai_addrlen;//

소켓 주소인

ai_addr

의 길이

struct sockaddr *ai_addr;//

소켓 주소

char *ai_canonname;//Canonical

네임

struct addrinfo *ai_next;//

연결리스트에서 다음

addrinfo

의 위치

};

(8)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

네임 Resolve 예제 (1/2)

GetAddrInfo.c

1 // ... include files here ..

7 int main(int argc, char *argv[]) {

89 if (argc != 3) // 인자의 개수가 알맞은지 확인

10 DieWithUserMessage("Parameter(s)", "<Address/Name> <Port/Service>");

1112 char *addrString = argv[1]; // 서버의 IP/도메인 네임 13 char *portString = argv[2]; // 서버의 포트/ 서비스 이름 1415 // 반홖 받을 주소의 형태를 지정

16 struct addrinfo addrCriteria; // 주소 형태 구조체

17 memset(&addrCriteria, 0, sizeof(addrCriteria)); // ‘0’으로 초기화

18 addrCriteria.ai_family = AF_UNSPEC; //임의의 주소 버젂 반홖(IPv4, IPv6모두) 19 addrCriteria.ai_socktype = SOCK_STREAM; // 스트림 프로토콜 반홖 요청 20 addrCriteria.ai_protocol = IPPROTO_TCP; // TCP 프로토콜 반홖 요청 2122 // 주어진 주소/서비스에 대한 주소 반홖을 요청

23 struct addrinfo *addrList; // 반홖 받을 주소가 저장될 리스트 24

(9)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

네임 Resolve 예제 (2/2)

25 int rtnVal = getaddrinfo(addrString, portString, &addrCriteria, &addrList);

26 if (rtnVal != 0)

27 DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal));

2829 // 반홖된 주소 정보를 출력

30 for (struct addrinfo *addr = addrList; addr != NULL; addr = addr->ai_next) { 31 PrintSocketAddress(addr->ai_addr, stdout);

32 fputc('\n', stdout);

33 }34

35 freeaddrinfo(addrList); // getaddrinfo()에 의해 할당된 메모리를 해제 3637 exit(0);

38 }

(10)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

네임 Resolve 실행 예시

<= 로컬 DB resolve

<= 분산 DB(DNS) resolve

<= 서비스 resolve

<= IPv6 resolve

<= 분산 DB(DNS) resolve, 등록된 모듞

IP반홖

(11)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

getaddrinfo()를 활용한 주소 범용 (Generic) 코드

주소 범용(Generic) 코드란?

 주소 버젂(IPv4, IPv6)에 관계없이 동작하는 코드

기존 코드의 문제점

 주소 구조체를 지정하여 사용할 경우, 사용자의 각기 다른 주소 버젂의 입력에 유연하게 대처하지 못함

 IPv4 코드는 IPv4 주소만 처리하고 IPv6 코드는 IPv6 주소만 처리

이유 : 각 주소 버젂에 맞는 구조체가 코드에 묶임

해결 방안

 addrInfo를 처리하는 getaddrinfo 함수를 사용하여 resolving한 결과를 처리

사용자 주소 입력(IPv4 or IPv6 or DNS)

getaddrinfo를 수행하여 가용한 주소 젂부 반홖

각 개별 주소에 대하여 연결 혹은 연결 대기 시도

(12)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

SetupTCPClientSocket(): 서버와 연결을 수행하고 연결된 소켓을 반환

//SetupTCPClientSocket()

//서버 호스트의 주소(IPv4, IPv6, DNS) 및 서비스 이름을 입력하면 서버와 연결된 소켓을 반홖 int SetupTCPClientSocket(const char *host, const char *service) {

struct addrinfo addrCriteria; // 반홖받을 주소의 형태를 담을 구조체 memset(&addrCriteria, 0, sizeof(addrCriteria)); // ‘0’으로 초기화 addrCriteria.ai_family = AF_UNSPEC; // IPv4와 IPv6 모두 반환 요청 addrCriteria.ai_socktype = SOCK_STREAM; // 스트리밍 소켓만 반홖 요청 addrCriteria.ai_protocol = IPPROTO_TCP; // TCP 프로토콜만 반홖 요청 struct addrinfo *servAddr; // 서버의 주소를 반홖 받을 구조 구조체 int rtnVal = getaddrinfo(host, service, &addrCriteria, &servAddr);

if (rtnVal != 0)

DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal));

int sock = -1;

for (struct addrinfo *addr = servAddr; addr != NULL; addr = addr->ai_next) { // TCP를 이용하여 안정된 소켓을 생성

sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);

if (sock < 0)

continue; // 소켓 생성 실패, 다음 주소로 시도 // 에코 서버에 연결 시도

if (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0) break; // 소켓 연결 성공, 반복문을 탈출하고 소켓을 반홖 close(sock); // 소켓 연결 실패, 다음 주소로 다시 시도 sock = -1;

freeaddrinfo(servAddr); // getaddrinfo()의 결과로 반홖된 메모리를 회수} return sock;

}

(13)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

SetupTCPServerSocket(): 서버의 주소를 획득하고 bind 및 listen수행(1/2)

SetupTCPServerSocket()

1 static const int MAXPENDING = 5; // 최대 연결 대기 수 23 int SetupTCPServerSocket(const char *service) {

4 // 서버 주소 구조체의 생성 5 struct addrinfo addrCriteria;

6 memset(&addrCriteria, 0, sizeof(addrCriteria));

7 addrCriteria.ai_family = AF_UNSPEC; // IPv4, IPv6 주소 모두 받아들임 8 addrCriteria.ai_flags = AI_PASSIVE;

9 addrCriteria.ai_socktype = SOCK_STREAM;

10 addrCriteria.ai_protocol = IPPROTO_TCP;

1112 struct addrinfo *servAddr;

13 int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr);

14 if (rtnVal != 0)

15 DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal));

1617 int servSock = -1;

18 for (struct addrinfo *addr = servAddr; addr != NULL; addr = addr->ai_next) { 19 // TCP 소켓 생성

20 servSock = socket(servAddr->ai_family, servAddr->ai_socktype, 21 servAddr->ai_protocol);

22 if (servSock < 0)

23 continue; // 소켓 생성 실패, 다음주소로 재시도

(14)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

SetupTCPServerSocket(): 서버의 주소를 획득하고 bind 및 listen수행(2/2)

SetupTCPServerSocket()

25 26 if ((bind(servSock, servAddr->ai_addr, servAddr->ai_addrlen) == 0) &&

27 (listen(servSock, MAXPENDING) == 0)) { 28 // 소켓의 지역 주소를 출력

29 struct sockaddr_storage localAddr;

30 socklen_t addrSize = sizeof(localAddr);

31 if (getsockname(servSock, (struct sockaddr *) &localAddr, &addrSize) < 0) 32 DieWithSystemMessage("getsockname() failed");

33 fputs("Binding to ", stdout);

34 PrintSocketAddress((struct sockaddr *) &localAddr, stdout);

35 fputc('\n', stdout);

36 break;

37 }

3839 close(servSock); // 소켓을 종료하고 다시 시도 40 servSock = -1;

41 }42

4344 freeaddrinfo(servAddr);

4546 return servSock;

47 }

(15)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부 AcceptTCPConnection(): 클라이언트의 연결을 처리

// AcceptTCPConnection()

//

클라이언트의 연결을 처리하고 연결된 소켓을 반환 1 int AcceptTCPConnection(int servSock) {

2 struct sockaddr_storage clntAddr; // 클라이얶트 주소 3 // 클라이얶트 주소 구조체 길이 설정(입출력 파라미터) 4 socklen_t clntAddrLen = sizeof(clntAddr);

56 // 클라이얶트의 연결을 대기

7 int clntSock = accept(servSock, (struct sockaddr *) &clntAddr,

&clntAddrLen);

8 if (clntSock < 0)

9 DieWithSystemMessage("accept() failed");

1011 // 이때 clntSock는 클라이얶트에 연결됨 1213 fputs("Handling client ", stdout);

14 PrintSocketAddress((struct sockaddr *) &clntAddr, stdout);

15 fputc('\n', stdout);

1617 return clntSock;

18 }

(16)

목포해양대 해양전자통신공학부 목포해양대 해양전자통신공학부

IPv4-IPv6 상호 연결

상호 연결 조건

 IPv4 젂용 프로그램의 경우

상호 종단갂 IPv4 지원

 IPv6 젂용 프로그램의 경우

상호 종단갂 IPv6 지원

 IPv4, IPv6 범용 프로그램의 경우

상호 종단 모두 IPv4를 사용하거나 상호 종단 모두 IPv6를 사용하는 경우

단, 듀얼 스택 시스템의 경우, IPv4와 IPv6 갂 연결이 가능

듀얼 스택(dual stack) 시스템

 IPv4 및 IPv6를 동시에 지원하는 시스템

참조

관련 문서

MR: Start and end mode output selection, shown here as 0 (output an END output signal on a high or low limit error so that the next weld cycle can start)a. The other selection is

소켓 으로 부터 InputStream과 OutputStream 생성 소켓 을 이용한 통신.. 소켓

소켓 으로 부터 InputStream과 OutputStream 생성 소켓 을 이용한 통싞. 소켓

OTT 등 동영상 서비스 OTT 등 동영상 서비스 유료 이용 현황.. OTT 등 동영상 서비스 OTT 등 동영상 서비스 이용시 개인정보에 대한 우려 및 개인 정보 활용 동의 정도..

의견제출자의 성명(단체인 경우 단체명과 대표자명), 주소,

This thesis is focused on network connecting technique of using embedded Linux and implementing remote control system base function using TCP/IP with

 PC에 저장된 명령어 주소가 시스템 주소 버스로 출력되기 전에 일시적으로 저장되는 주소 레지 스터.  기억장치 버퍼

 IP 주소를 할당하는 특정 서버가 전송하는 정보 그대로 컴퓨터에서 자동으로 설정하는 방식..  DHCP(Dynamic Host