소켓

- 소켓(socket)은 네트워크를 통한 입/출력을 하기 위해 사용자에게 필요한 수단을 제공하는 응용 프로토콜 인터페이스

- 소켓을 활용한 네트워크 응용 프로그램을 통해 네트워크 상에서 데이터를 송/수신

소켓은 OS 수준 API에서 양방향 네트워크의 종단간 연결과 전송을 할 수 있다.

 

네트워크 입/출력을 위한 요소

프로토콜(Protocol)

소스 IP 주소(Source IP Address)

소스 포트 번호(Source Port Address)

목적지 IP 주소(Target IP Address)

목적지 포트 번호(Target Port Address)

 

Socket Interface API

프로그램에서 네트어크 통신 서비스를 받을 때의 Socket API

- <sys/socket.h>

 

 

 

 

소켓 생성

● socket() 을 사용하여 소켓 생성

- 소켓 프로그래밍에서 통신 창구 역할

- 통신을 위한 end-point 생성

- 소켓 번호 리턴

 

● 동작

System call: int socket (int domain, int type, int protocol)

- 명시된 domain, type, protocol의 명명되지 않은 소켓을 생성

- 소켓 생성 성공시 : 새로 생성된 소켓에 연관된 파일 기술자 (serverFd)를 반환, 실패시 -1,errno도 설정

serverFd=socket(AF_UNIX, SOCK_STREAM, DEFAULT_PROTOCOL);

 

 

소켓 구조체

● 도메인(domain) 

- 서버와 클라이언트 소켓이 존재하는 장소를 지칭

 

● 유형(type)

- 클라이언트와 서버 사이에 존재할 수 있는 통신 유형 결정

 

● 프로토콜(protocol)

- 소켓 유형을 구현하는 저급의 수단을 명시

 

도메인

● 소켓 생성시 인자로 사용

- 주소 바인딩을 하지 않고라도 소켓을 생성할 때 사용 도메인 설정 필요

- BSD 소켓 개발시, TCP/IP 역시 개발 중

 

●PF(Protocol Family): 프로토콜 군

- PF_INET, PF_LOCAL(PF_UNIX)

 

●AF(Address Family): 주소 군

- AF_INET, AF_LOCAL(AF_UNIX)

 

소켓 : 패밀리

●지원하는 프로토콜 그룹 중에서 사용하려는 소켓이 적용될 프로토콜을 선택

Family Protocol

프로토콜 상수 설명

AF_UNIX

유닉스 기본 파일 체계 소켓
AF_INET IP4의 인터넷 프로토콜

AF_INET6

IP6의 인터넷 프로토콜

AF_NS

Xerox 네트워크 시스템 프로토콜

AF_ISO

ISO 프로토콜

AF_IPX

Novell IPX 프로토콜

AF_APPLETALK

Appletakl DDS

● 프로토콜

-여러 소켓 형태를 제공하는 경우 사용, 기본 값은 0

 

소켓 : 형식 (Type)

● Generic Type과 Protocol-Specific Type으로 구분

- Socket 인터페이스 구현시 C언어에 void 타입이 없었음

- 연결 지향형과 비 인결형, 저수준 소켓 프로토콜 제어형

 

● 저 수준 프로토콜

- IP 프로토콜과 같은 레벨에 있는 프로토콜을 사용 시 필요

- TCP/UDP 보다 하위 계층으로 사용이 까다로운 반면 직접적인 제어가 가능 

Type 각 Type 상수에 대한 설명
SOCK_STREAM TCP (스트림 소켓)
SOCK_DGRAM UDP (데이터그램 소켓)
SOCK_RAW Raw 소켓

 

소켓 프로그래밍

 

 

 

 

 

 

소 지정

● 클라이언트는 일반적으로 주소를 바인딩 하지 않는다.

- 클라이언트가 서버와의 통신을 시도할 때 커널이 자동으로 지정

- 서버와 통신하는 동안만 주소가 유효(임시적 주소)

 

● 서버는 일반적으로 스스로 주소를 지정 작업 수행 (고정 주소)

 

IP 주소와 포트번호

● Server에 접속하기 위해 필요한 것

- IP 주소(address), 포트 번호(port number)

 

● 포트번호

- TCP/IP 프로토콜은 주어진 호스트 컴퓨터 내에서 여러 곳의 목적지로 데이터를 전송하기 위하여 서로 다른 포트를 사용

- 한 클라이언트 컴퓨터가 특정 어플리케이션을 사용하기 위하여 호스트에 연결 할 경우, 그 어플리케이션에 접속할 포트가 사용

 

포트번호

● 포트 번호를 사용하는 이유

- 동시에 한 개의 IP 주소(Address)로 여러 클라이언트 접속 가능

 

소켓 네이밍

● 서버가 명명되지 않은 소켓 생성시, bind()를 사용하여 이름 부여, 성공시 0, 실패시 -1

 

● 동작: System call: int bind(int fd, struct sockadrr* address, int addressLen)

- address에 저장된 소켓 주소를 가지는 파일 기술자 fd를 명명되지 않은 소켓에 연관시킴

- addressLen는 주소 구조체의 길이를 포함

- 입력될 주소의 유형과 값은 소켓 도메인에 의함

 

 

기본 자료형

● sockaddr 구조체

- 기본 적인 소켓 주소 구조체, 호환성을 ㅜ이해 존재

- 변수 : 구조체의 크기, Family Type, 소켓의 주소 데이터

 

● sockaddr_in 구조체

- IPv4 소켓 주소 구조체

- 주소를 담기 위해 in_addr 구조체 사용

- 변수 : 구조체의 크기, Family Type, 소켓의 주소 및 포트 번호

 

● sockaddr_un 구조체 : 유닉스 호스트 상의 통신

- 유닉스 소켓 주소 ㄱ조체

- 동일 호스트에서의 통신이 일반 TCP 통신보다 두 배 빠름

- 변수 : 소켓 상수, 호스트 경로

 

도메인에 따른 구조체 항목

● AF_UNIX 도메인

- sockaddr_un 구조체의 항목

항목 값부여
sun_family AF_UNIX
sun_path 소켓의 완전한 경로 이름으로, 최대 길이는 180문자

 

●AF_INET 도메인

- sockaddr_in 구조체의 항목

항목 값부여
sin_family AF_INET
sin_port 인터넷트 소켓의 포트 번호
sin_addr in_addr 유형의 구조체
sin_zero Padding Byte(0로 남겨둔다)

 

 

 

바이트 순서 (Byte Order) 71p lnp_day2

2바이트 이사의 데이터를 메모리에 저장하는 방법, 상위 바이트의 값을 메모리에서 어느쪽으로 두느냐

 

Big-Endian

상위 바이트 값이 메모리상에 먼저(번지수가 작은 위치) 표시

호스트 바이트 순서(Host Byte Order): Motolora 68000 계열

 

Little-Endian

하위 바이트 값이 메모리상에서 먼저(번지수가 작은 위치) 표시

호스트 바이트 순서(Host Btye Order): Intel x86 계열

 

바이트 오더 확인

Linux에서 lscpu 명령으로 확인 가능.

C에서 MBS 값에 따라 확인 가능

endian_conv.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <arpa/inet.h>
 
int main(int argc, char *argv[])
{
    unsigned short host_port=0x1234;
    unsigned short net_port;
    unsigned long host_addr=0x12345678;
    unsigned long net_addr;
 
    net_port=htons(host_port);
    net_addr=htonl(host_addr);
 
    printf("Host ordered port: %#x \n",host_port);
    printf("Network ordered port: %#x\n",net_port);
    printf("Host ordered address: %#lx\n",host_addr);
    printf("Network ordered address: %#lx\n",net_addr);
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

IP 주소 처리

문자열 <-> 숫자 변환 함수 제공 , 프로그램 작성이 용이

inet_addr() : 문자열 IP 주소를 32비트 IP주소로 변환

inet_aton() : 문자열 IP 주소를 32비트 IP주소로 변환

inet_ntoa() : 32비트 IP주소를 문자열 IP 주소로 변환

inet_network() : IP 주소를 호스트 순서 -> 네트워크 순서로 변환

inet_lnaof() : IP 주소에서 호스트 주소 부분 추출

inet_netof() : IP 주소에서 네트워크 주소 부분 추출

inet_makeaddr() : 분리된 호스트 주소와 네트워크 주소를 결합

 

주소 변환(1)

● 32비트 이진 바이너리 주소를 'Dotted Decimal' 형식의 문자열로 또는 그 반대로 변환하여 주는 기능

● unsigned long int inet_addr(const char * strptr);

- 'Dotted Decimal' 문자열 형태의 주소를 네트워크 바이트 순서를 갖는 이진 바이너리로 변환

- 입력 값이 적절치 못할 경우 INADDR_NONE('-1')을 반환

- '-1'은 'Dotted Decimal'로 표현시 '255.255.255.255' 이므로 유효성 검사가 반드시 필요

 

inet_addr.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <arpa/inet.h>
 
int main(int argc,char *argv[])
{
    char *addr1="1.2.3.4";
    char *addr2="1.2.3.256";
 
    unsigned long conv_addr=inet_addr(addr1);
    if(conv_addr==INADDR_NONE)
        printf("Error occured!\n");
    else
        printf("Network ordered integer addr: %#lx \n",conv_addr);
 
    conv_addr=inet_addr(addr2);
    if(conv_addr==INADDR_NONE)
        printf("Error occureded\n");
    else
        printf("Network ordered integer addr: %#lx \n\n",conv_addr);
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(int argc, char **argv)
{
    int z,sck_inet;
    struct sockaddr_in adr_inet;
 
    sck_inet = socket(AF_INET,SOCK_STREAM, 0);
    if(sck_inet==-1){
        perror("socket()");
        return -1;
    }
 
    memset(&adr_inet,0,sizeof(adr_inet));
    adr_inet.sin_family=AF_INET;
    adr_inet.sin_port =htons(8000);
    adr_inet.sin_addr.s_addr = inet_addr("127.0.0.1");
 
    if(adr_inet.sin_addr.s_addr == INADDR_NONE) {
        perror("bad address.");
        return -1;
    }
 
    z=bind(sck_inet, (struct sockaddr *)&adr_inet, sizeof(adr_inet));
    if(z==-1){
        perror("bind()");
        return -1;
    }
    if(listen(sck_inet,5)==-1)
    {
        printf("listen error");
    }
 
 
    system("netstat -pa --tcp 2>/dev/null | grep inetaddr");
 
    close(sck_inet);
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

주소변환(2)

● int inet_aton(const char * strptr, struct int_addr * addrptr);

'Dotted Decimal' 형태의 문자열을 바이너리 형태로 변환

- 'strptr'로 들어온 'Dotted Decimal' 형태의 문자열은 변환되어 'in_addr' 타입의 'addrptr'에 저장됨

- 주소가 올바르다면 '0' 이 아닌 값, 그렇지 않다면 '0'을 반환

 

● char *inet_ntoa(struct inaddr inaddr);

- 'in_addr' 형의 바이너리 주소 'inaddr' 을 'Dotted Decimal' 형태의 문자열로 변경

- 반환 되는 문자열은 정적으로 할당된 버퍼에 저장

- 함수의 연속적인 호출은 버퍼를 중복하여 덮어 쓰므로 주의

 

inet_ntoa.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>
#include <string.h>
#include <arpa/inet.h>
 
int main(int argc,char *argv[])
{
    struct sockaddr_in addr1, addr2;
    char *str_ptr;
    char str_arr[20];
 
    addr1.sin_addr.s_addr=htonl(0x1020304);
    addr2.sin_addr.s_addr=htonl(0x1010101);
 
    str_ptr=inet_ntoa(addr1.sin_addr);
    strcpy(str_arr,str_ptr);
    printf("Dotted-Decimal notation1:%s \n",str_ptr);
 
    inet_ntoa(addr2.sin_addr);
    printf("Dotted-Decimal notation2: %s \n",str_ptr);
    printf("Dotted-Decimal notation3: %s \n",str_arr);
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

 

주소 변환(3)

● unsigned long inet_network(const char *addr);

- Dotted-quad된 IP 주소를 32비트 호스트 순서 주소로 변환

- 마스크 값을 호스트 비트 혹은 네트워크 비트에 적용 할 때 사용

- 반환 값은 호스트 순서 32비트 IP 주소, 실패시 0xFFFFFFFFF(모두 1)

 

inet_network()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(int argc,char **argv)
{
    int x;
    const char *addr[] = {
        "44.135.86.12",
        "127.0.0.1",
        "172.16.23.95",
        "192.168.9.1"
    };
 
    unsigned long net_addr;
 
    for(x=0;x<4;++x){
        net_addr = inet_network(addr[x]);
        printf("%14s = 0x%08lx net 0x%08lx\n",
        addr[x],net_addr,(unsigned long)htonl(net_addr));
    };
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

주소변환 (4)

● unsigned long inet_lnaof(struct in_addr addr)

- 32비트 IP 주소(네트워크 바이스 순서) 에서 네트워크 ID 부분을 제외한 호스트 ID 부분만을 변환(호스트 순서)

 

주소변환 (5)

● unsigned long inet_netof(struct in_addr addr);

- 32비트 IP 주소 (네트워크 바이스 순서) 에서 네트워크 ID 부분을 제외한 네트워크 ID 부분만을 반환(호스트 순서)

 

● struct in_addr inet_makeaddr (int net, int host);

- 네트워크 ID와 호스트 ID를 결합하여 원래의 IP주소를 생성

inet_makeaddr.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
 
int main(int argc, char **argv)
{
    int x;
    struct sockaddr_in adr_inet;
    const char *addr[] = {
        "44.135.86.12",
        "127.0.0.1",
        "172.16.23.95",
        "192.168.9.1"
    };
    unsigned long net, hst;
 
    for(x=0;x<4;++x){
        memset(&adr_inet, 0sizeof(adr_inet));
        adr_inet.sin_family = AF_INET;
        adr_inet.sin_port = htons(9000);
        if(!inet_aton(addr[x],&adr_inet.sin_addr)) puts("bad address.");
 
        hst=inet_lnaof(adr_inet.sin_addr);
        net = inet_netof(adr_inet.sin_addr);
        printf("%14s : net=0x%08lx host=0x%08lx\n",inet_ntoa(adr_inet.sin_addr),net,hst);
 
        memset(&adr_inet, 0sizeof(adr_inet));
        adr_inet.sin_family = AF_INET;
        adr_inet.sin_port = htons(9000);
        adr_inet.sin_addr = inet_makeaddr(net,hst);
 
        printf("inet_makeaddr : %s\n\n",inet_ntoa(adr_inet.sin_addr));
    };
 
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

 

소켓 주소 획득

● int getsockname(int sockfd, struct sockaddr *name, socklen_t *namelen);

● int geteername(int sockfd, struct sockaddr *name, socklen_t *namelen);

- 지역 소켓과 원격 소켓의 주소를 반환

- 성공시 0, 실패시 -1과 errno 설정

- namelen으로 변수를 지정

 

getsockname.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(int argc,char **argv)
{
    int z,sck_inet,len;
    struct sockaddr_in adr_inet, inet;
 
    sck_inet = socket(AF_INET,SOCK_STREAM,0);
    if(sck_inet == -1){
        perror("socket()");
        return -1;
    }
 
    memset(&adr_inet,0,sizeof adr_inet);
    adr_inet.sin_family = AF_INET;
    adr_inet.sin_port = htons(8000);
    if(!inet_aton("127.0.0.1",&adr_inet.sin_addr)){
        perror("bad address");
        return -1;
    }
 
    z=bind(sck_inet,(struct sockaddr*)&adr_inet, sizeof(adr_inet));
    if(z==-1){
        perror("bind()");
        return -1;
    }
 
    len=sizeof(inet);
    z=getsockname(sck_inet,(struct sockaddr*)&inet,&len);
    if(z==-1){
        perror("getsockanme()");
        return -1;
    }
 
    printf("Address : %s:%u\n",inet_ntoa(inet.sin_addr),
            (unsigned)ntohs(inet.sin_port));
 
    close(sck_inet);
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

 

 

Domain 주소

 

DNS Server

도메인 이름을 공인IP 주소로 검색해주는 인터넷 서비스

- DNS server는 분산 데이터베이스 시스템

- 로컬 DNS Resolver가 DNS port 53번을 통해 검색

- ROOT -TOP Levle 로 분산된 시스템

 

DNS (Domain Name System)

영문으로 구성되는 도메인 이름을 IP Address 로 변환하기 위해 필요

도메인 이름과 그에 대응되는 IP Address 가 저장된 테이블을 가지고 있음

IP Address 로의 변환 요청이 발생하면 테이블을 검색하여 변환

 

원격지 호스트 정보(1)

● struct hostent *gethostbyname(const char * hostname);

- 전달 값으로 호스트의 이름(도메인을)을 받아서 hostent 구조체에 결과 값을 돌려주는 함수

- 도메인 이름을 전달하면 DNS Resolver를 통해서 IP 주소를 검색

 

● struct hostent *gethostbyaddr(const char * addr, size_t len, int family);

- 호스트의 IP주소 (바이너리 형태의 주소)를 이용하여 해당 호스트에 대한 정보를 저장

- addr은 호스트 IP주소이고 len 은 IP 주소의 크기 (IPv4 = 4, IPv6 = 16)

- IP 주소를 전달하면 DNS Resolver를 통해서 도메인 이름을 검색

 

● int gethostname(char * name, size_t namelen);

- 현재의 호스트 이름을 반환

- 전달 인자 name은 호스트의 이름을 저장할 곳의 주소

- namelen 은 name의 바이트 길이

-성공한 경우 0, 실패하면 -1

 

●struct servent *getservbyname(const char * servname, const char * protoname);

- 해당 호스트에서 진행되고 있는 서비스에 대한 각 정보를 서비스에 대한 이름과 해당 프로토콜로 얻을 수 있게 해주는 함수

 

● struct servent *getservbyport(int port,const char * protoname);

- 해당 호스트에서 진행되고 있는 서비스에 대한 각 정보를 포트 번호로 얻을 수 있게 해주는 함수

- 수행 중 에러 발생 시에는 결과 값으로 반환 NULL 반환

 

 

Domain resolving : nslookup

nslookup

- DNS server에 ip, name 을 질의해 얻는다

 

DNS에 특정 종류(레코드)에 대해서 검색할 때에는 'set type' 명령을 이용

- set types=ns

- set type=all

 

 

gethostbyname.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main(int argc,char *argv[])
{
    int i;
    struct hostent *he;
    struct in_addr **addr_list;
 
    if(argc != 2) {
        fprintf(stderr,"usage:ghbn hostname\n");
        return 1;
    }
 
    if((he=gethostbyname(argv[1]))==NULL){
        herror("gethostbyname");
        return 2;
    }
 
    printf("Name : %s\n", he->h_name);
    printf("IP addresses: ");
    addr_list = (struct in_addr **)he->h_addr_list;
    for(i=0;addr_list[i] != NULL; i++)
    {
        printf("%s ",inet_ntoa(*addr_list[i]));
    };
    printf("\n");
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

gethostbyaddr.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handling(char *message);
 
int main(int argc, char *argv[])
{
    int i;
    struct hostent *host;
    struct sockaddr_in addr;
    if(argc!=2) {
        printf("Usage : %s <IP>\n", argv[0]);
        exit(1);
    }
 
    memset(&addr, 0sizeof(addr));
    addr.sin_addr.s_addr=inet_addr(argv[1]);
    host=gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);
    if(!host)
        error_handling("gethost... error");
 
    printf("Official name: %s \n", host->h_name);
 
    for(i=0; host->h_aliases[i]; i++)
        printf("Aliases %d: %s \n", i+1, host->h_aliases[i]);
    
    printf("Address type: %s \n"
        (host->h_addrtype==AF_INET)?"AF_INET":"AF_INET6");
 
    for(i=0; host->h_addr_list[i]; i++)
        printf("IP addr %d: %s \n", i+1,
                    inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));    
    return 0;
}
 
void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

 

 

실습: IP의 Netmask

1. IP Address 준비 

2. memcpy로 sockaddr_in에 할당

3. 최상위 바이트 검사

4. 결과 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static struct {
 unsigned char ip[4];
} addresses[] = {
 {{441358612}}, {{127001}}, //샘플 IP
 {{172162395}}, {{19216891}}
};
for (x = 0; x < 4++x) {
 memcpy(&adr_inet.sin_addr.s_addr, addresses[x].ip, 4);
 msb = *(unsigned char *)&adr_inet.sin_addr.s_addr;
 if ((msb & 0x80== 0x00) { //0x80: 1000
 class = 'A';
 } else if ((msb & 0xC0== 0x80) { //0xC0: 1100
 class = 'B';
 } else if ((msb & 0xE0== 0xC0) { //0xE0: 1110
 class = 'C';
 } else if ((msb & 0xF0== 0xE0) { //0xF0: 1111
 class = 'D';
 } else {
 class = 'E';
 }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

inet_pton () : 문자 IPv4, IPv6 주소를 바이너리 형으로 전환

#include <arpa/inet.h>

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

 

inet_ntop() : 바이너르 IPv4, IPv6 주소를 문자형으로 전환

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

 

 

IPv4, IPv6 네트워크 정보 함수

IPv4 전용 gethostbyaddr, gethostbyname 은 다음 IPv4, IPv6 대응 함수에 통합

getaddrinfo() : 호스트 이름, IP주소 관련 정보를 얻는 함수

getnameinfo() : 주소에서 이름을 변환해 준다

freeaddrinfo() : addrinfo 메모리를 해제

gai_strerror : getaddrinfo, getnameinfo 에러 코드를 문자로 해석

getaddrinfo_a() : 여러 이름을 다룰 수 있다

 

getaddrinfo()

gethostbyname, gethostbyaddr, inet_addr, inet_aton, inet_pton 통합한 함수

#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의 점으로 구분하는 10진 주소 문자열이거나 IPv6의 16진 문자열

- service : 서비스 이름 혹은 10진수로 표현한 포트 번호 문자열

- hints : hint로 줄 addrinfo 구조체에 주소 정보를 채운. 별도의 hint를 제공하지 않을 경우, NULL

- res : 결과 addrinfo

- return : 성공시 0, 그외 값은 에러 코드

 

addrinfo

네트워크 주소정보(인터넷 주소)와 호스트 이름을 표현 

1
2
3
4
5
6
7
8
9
10
11
12
struct addrinfo
{
 int ai_flags; /* 추가적인 옵션 정. 여러 flag를 bitwise OR-ing */
 int ai_family; /* AF_INET, AF_INET6, AF_UNSPEC */
 int ai_socktype; /* SOCK_SREAM, SOCK_DGRAM */
 int ai_protocol; /* IPv4,IPv6의 IPPROTO_xxx 같은 값. */
 socklen_t ai_addrlen; /* socket 주소인 ai_addr의 길이를 나타냄 */
 char *ai_canonname; /* 호스트의 canonical name을 나타냄 */
 struct sockaddr *ai_addr; /* socket 주소를 나타내는 구조체 포인터 */
 struct addrinfo *ai_next; /* 주소정보 구조체 addrinfo는 linked list이다. 다음
데이터의 포인터 */
}; 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

getaddrinfo.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
 
int main(int argc,char const *argv[])
{
    int status;
    struct addrinfo hints;
    struct addrinfo *rslt; // result
    const char *addr;
    if (argc < 2)
    {
        printf("사용법: %s <domain name>\n", argv[0]);
        exit(1);
    }
 
    memset(&hints, 0sizeof hints); //구조체를 0으로 초기화
    hints.ai_family = AF_UNSPEC; // IPv4, IPv6 모든 결과
    hints.ai_socktype = SOCK_STREAM; // TCP Stream sockets
    hints.ai_flags |= AI_CANONNAME;
 
    if((status=getaddrinfo(argv[1],NULL,&hints,&rslt))!=0)
    {
        fprintf(stderr, "getaddrinfo: %s\n",gai_strerror(status));
        exit(EXIT_FAILURE);
    }
 
    for(struct addrinfo *aip = rslt; aip!=NULL; aip=aip->ai_next)
    {
        char addrstr[NI_MAXHOST];
        void *ptr; //pointer to binary address
        in_port_t port; // port number
 
        switch(aip->ai_family)
        {
            case AF_INET:
                ptr=&((struct sockaddr_in *)aip->ai_addr)->sin_addr;
                port = ntohs(((struct sockaddr_in *)aip)->sin_port);
                break;
            case AF_INET6:
                ptr=&((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr;
                port=ntohs(((struct sockaddr_in6 *)aip)->sin6_port);
                break;
            default:
                break;
        }
        // Convert binary to character
        inet_ntop(aip->ai_family, ptr, addrstr, sizeof addrstr);
        printf("Host name : %s (%s) \n", addrstr, aip->ai_canonname);
    }
 
    freeaddrinfo(rslt); // No longer needed
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4f; text-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none; color:white">cs

 

 

+ Recent posts