바이트 순서와 네트워크 바이트 순서

네트워크 바이트 순서와 인터넷 순서가 어떤 관계가 있는지

시스템에 따라 Big Endian / Little Endian 사용 방식이 다르다.

Big Endian - 상위 바이트의 값을 작은 번지수에 저장

ex. 0x12345678 은 가장 낮은 번지부터 0x12 0x34 0x56 0x78 순서로 담긴다. (상위 바이트는 12이다.)


Little Endian - 상위 바이트의 값을 큰 번지수에 저장

ex. 0x12345678은 0x78 0x56 0x34 0x12 순서로 담긴다.


데이터 송수신 과정에서 데이터 저장방식의 차이 문제가 발생할 수 있음 따라서 네트워크 데이터 송수신을 할 땐 약속이 필요함

보내는 쪽, 받는 쪽 모두 BigEndian / LittleEndian이든 상관없이 보내는 바이트의 순서는 낮은 주소부터 전송(빅엔디안)한다는 것을 알려야한다.

네트워크 바이트 순서는 BigEndian 기준! (낮은 주소의 데이터 번지부터 전송!) 낮은 주소를 significant byte로 취급하라고 알려줌 )




바이트 순서의 변환

htons - host의 메모리 속 데이터 순서가 bigendian이든 littleendian이든 상관없이 network byte(bigendian) 타입으로 바꿔라


이식성을 위해서 변경되지 않는다 하더라도 변경을 취해준다!


0x1234에서 1 하나는 4bit이고 12가 1byte를 나타낸다.



문자열 정보를 네트워크 바이트 순서의 정수로 변환


inet_addr(const char* string)

( ).( ).( ).( ) 형태의 문자열을 4바이트의 정수 배열(in_addr_t: 32비트 정수형)로 바꿔주는 함수이다. 

성공 시 Big Endian으로 변환된 32비트 정수값

실패 시 INADDR_NONE 반환

또한 표현 가능 범위를 체크하여 비트 수를 초과하는 값의 변환을 시도하면 INADDR_NONE반환


inet_aton(const char* string, struct in_addr* addr);

기능상으로 inet_addr 함수와 동일하다. 다만 in_addr형 구조체 변수에 변환의 결과가 저장된다는 점에서 차이를 보인다.

(struct sockaddr_in 안에 struct in_addr형 sin_addr 변수/ struct in_addr 안에는 in_addr_t 타입 s_addr변수가 있음)

성공시 1(true), 실패 시 0(false) 반환


주로 inet_addr를 많이 사용. inet_aton을 지원하지 않는 경우가 많기 때문


inet_ntoa

32bit ip 주소를 ASCII형(. . . .)으로 변환


Note. 항상 네트워크 바이트 순서로 저장을 함 -> htonl 이용


inet_ntoa 에 (객체).sin_addr 를 인자로 넘김





인터넷 주소의 초기화


memset 을 하는이유 : sockaddr_in 구조체 변수의 마지막 8byte 변수는 사용하지 않기 때문에 모두 0으로 채울 필요가 있다.

(sockaddr_in 구조체 변수).sin_addr.s_addr = inet_addr(문자열 형태의 IP주소)   - 여기서 문자열 형태의 IP주소는 "( ).( ).( ).( )" 형태

atoi로 문자열을 정수형으로 변환

Q. 왜 s_addr에는 htons로 변경하지 않나 ?

inet_addr에서 자동적으로 big endian 형식의 32bit 정수형을 반환함


이렇게 초기화한 값을 bind에 할당하게 됨


서버에서 주소정보를 설정하는 이유! (초기화한 값을 bind의 인자로 넘긴 경우)

초기화한 IP, PORT로 들어오는 데이터는 내게로 다 보내라!


클라이언트에서 주소정보를 설정하는 이유(초기화한 값을 connect의 인자로 넘긴 경우)

초기화한 IP, PORT로 연결을 해라



INADDR_ANY

현재 실행중인 컴퓨터의 IP를 소켓에 부여할 때 사용되는 것이 INADDR_ANY이다.

이는 서버 프로그램의 구현에 주로 사용된다.

이때 htonl(INADDR_ANY)형태로 대입한다.

4Byte unsigned int로 들어가 있으므로 데이터 순서만 정렬해서 넣어줌


이미 정해진 것을 사용하겠다는 의미

그러나 컴퓨터에 network interface card가 두개가 있을 땐 직접 지정해줘야 한다.

이때 INADDR_ANY를 쓰면 어느 것이 들어갈 지 모른다.


'CS & IT실무' 카테고리의 다른 글

IO 멀티플렉싱  (0) 2018.11.13
Half-Close - shutdown()  (0) 2018.10.05
소켓에 할당되는 IP주소와 PORT번호  (0) 2018.10.04

소켓을 생성한 다음에 서버의 경우 bind 함수를 사용해서 소켓에 주소를 부여할 수 있고, 클라이언트의 경우 connect함수 내부에서 자동으로 주소를 할당이 된다.

소켓의 주소라는 것이 어떻게 생겼는지 소켓에 그 주소를 어떻게 바인딩하는지가 목표

IPv4 인터넷 주소의 체계

처음 8비트는 네트워크를 구분하고 나머지 24비트는 네트워크 안의 호스트들을 구분하는 데 사용된다.

일반적으로 클래스C를 사용.

3바이트로 인하대학교 네트워크를 발견하고, 네트워크 내부에서 사용하는 호스트들은 나머지 1바이트로 구분

클래스 A의 첫 번째 비트는 항상 0으로 시작
클래스 B의 첫 두 비트는 항상 10으로 시작
클래스 C의 첫 세 비트는 항상 110으로 시작
클래스 C에서 마지막 1바이트인 IP로 PC 시스템 하나를 구분하고 Port번호로 하나의 시스템에서 동작하고 있는 수많은 어플리케이션들을 구분한다. 그러나 어플리케이션과 port 하나를 구분하지 않는다. 소켓하나당 port가 하나를 구분하는 것

IP +Port 번호로 소켓하나를 구분하는 것

PORT번호는 16bit로, 따라서 그 값은 표현 0~(

-1)

0~1023은 잘 알려진 port(Well-known PORT)라 해서 이미 용도가 결정되어 있다.

IP와 PORT번호를 어떤 자료구조로 할당하는가?

IPv4 기반의 주소표현을 위한 구조체로 sockaddr_in이 있다. 이 변수안에 IP주소와 PORT번호 정보를 담는다.

1
2
3
4
5
6
struct sockaddr_in {
    sa_family_t        sin_family;
    uint16_t        sin_port;
    struct in_addr    sin_addr;
    char            sin_zero[8];
};
cs

이 안에는

- 주소체계를 나타내는 sin_family,

- PORT번호를 나타내는 sin_port(2byte),

- 32비트 IP주소를 나타내는 sin_addr(4byte),

- sin_zero[8](8byte) - 0으로 채움 (사용하지 않음)

까지4가지 변수가 있다.

여기서 sin_addr는 struct in_addr라는 구조체 타입인데, 이 변수 안에는 in_addr_t 라는 자료형을 갖는 s_addr 변수가 있다.

여기에 32bit IPv4 인터넷 주소 정보를 담는다.

이 자료형은 uint32_t로 정의되어 있는 데 왜 구분되어 사용되는 것일까?

이름을 보고 의미를 파악하게 하기위해, 해당 속성마다 이름을 구분하여 시스템 확장성을 위함이다. (즉, 직관성, 확장성)

sin_family는 PF(Protocol Family)인지 AF(Address Family)를 구분 - IPv4, IPv6 구분

sockaddr_in 구조체 변수는 bind 함수의 인자로 전달되는데 매개변수 형이 sockaddr으로 형변환을 해야만 한다.

sockaddr이 먼저 생겨나거 그 세부사항을 나눠서 표현하기 위해 sockaddr_in 구조체 타입을 생성한 것이라 생각하면 편한다.

sockaddr 타입 안에는 두 개의 변수가 있다. sin_family 변수는 sockaddr_in과 같다. 다른 하나는 sa_data[14]인데 sockaddr_in에서 sin_port, sin_addr, sin_zero[0] 총 14 byte의 정보가 sa_data에 포함된다. 따라서 IPv4에 맞춰서 sa_data의 14byte를 구분해놓은 것이 sockaddr_in 구조체 타입 변수이다.

따라서 우리는 sockaddr_in으로 정의했기 때문에 bind 로 넘길 때는 sockaddr로 강제 형변환을 하여 넘긴다.

'CS & IT실무' 카테고리의 다른 글

IO 멀티플렉싱  (0) 2018.11.13
Half-Close - shutdown()  (0) 2018.10.05
네트워크 바이트 순서와 인터넷 주소 변환  (0) 2018.10.04

+ Recent posts