인터넷 주소(Internet Adress)
- IPv4(Internet Protocol version 4) : 4바이트 주소체계(1234.1234.1234.1234)
- IPv6(Internet Protocol version 6) : 16바이트 주소체계(1234.1234.1234.1234.1234.1234.1234.1234)
: IPv4의 IP주소가 모두 고갈될 것을 염려하여 만들었다.
IPv4기반의 주소표현을 위한 구조체
struct sockaddr_in
{
sa_family_t sin_family; // 주소체계(Adress Family)
uint16_t sin_port; // 16비트 TCP/UDP PORT번호
struct in_addr sin_addr; // 32비트 IP주소
char sin_zero[8] // 사용되지 않음
};
struct in_addr
{
in_addr_t s_addr; //32비트 IPv4 인터넷 주소
};
- 구조체 분석
멤버 변수
sin_family
->프로토콜체계마다 적용하는 주소체계가 다르다. 예를 들어서 IPv4에서는 4바이트 주소체계를 사용하고 IPv6에서는 16비트 주소체계를 사용해야 한다.
->AF_INET : IPv4 인터넷 프로토콜에 적용하는 주소체계(AF = Adress Family)
->AF_INET6 : IPv6 인터넷 프로토콜에 적용하는 주소체계
->AF_LOCAL : 로컬 통신을 위한 유닉스 프로토콜의 주소체계
->AF_INET : IPv4 인터넷 프로토콜에 적용하는 주소체계(AF = Adress Family)
->AF_INET6 : IPv6 인터넷 프로토콜에 적용하는 주소체계
->AF_LOCAL : 로컬 통신을 위한 유닉스 프로토콜의 주소체계
sin_port
->소켓의 구분에 활용되는 것이 바로 Port번호이다. IP만 있다면 목적지 컴퓨터로 데이터를 전송할 순 있어도 해당 응용프로그램까지 전송할 수는 없지 않은가?
->16비트의 PORT번호를 저장하는 변수이다. 단, '네트워크 바이트 순서'로 저장해야 한다(이것은 아래에 추가 설명을 해놓을 것입니다.),
->16비트의 PORT번호를 저장하는 변수이다. 단, '네트워크 바이트 순서'로 저장해야 한다(이것은 아래에 추가 설명을 해놓을 것입니다.),
sin_addr
-> 32비트 IP주소를 저장한다. 이것 역시 '네트워크 바이트 순서'로 저장해야 한다.
sin_zero
-> 단순히 구조체 sockaddr_in와 크기를 맞추기 위해 존재하는 변수이다. 반드시 0으로 초기화해주어야 한다.
struct sockaddr
{
sa_family_t sin_family; // 주소체계(Address Family)
char sa_data[14]; // 주소정보
};
멤버변수
sa_data[14]
->IP주소와 PORT번호를 담고 있어야 하고, 남은 부분은 0으로 채울것을 bind함수는 요구하고 있다. 그렇기 때문에 sockaddr_in이라는 구조체가 필요한 것이다.
네트워크 바이트 순서와 인터넷 주소 변환
CPU에 따라서 4바이트 메모리 공간에 정수 1을 저장하는 방식이 달라진다.
00000000 00000000 00000000 00000001 -> 빅엔디안 : 상위 바이트의 값을 작은 번지수에 저장하는 방식
00000001 00000000 00000000 00000000 -> 리틀엔디안 : 상위 바이트의 값을 큰 번지수에 저장하는 방식
0x12345678이라는 데이터를 전송할 경우
빅엔디안 ------------------------------------> 리틀 엔디안
송신 0x78 -> 0x56 -> 0x34 -> 0x12 수신
0x12345678 0x78563412
그래서 결국 빅엔디안 방식으로 통일하기로 약속을 하였다.
바이트 순서의 변환
- unsigned short htons(unsigned short);
- unsigned short ntohs(unsigned short);
- unsigned long htonl(unsigned long);
- unsigned long ntohl(unsigned long);
여기서 h는 호스트(host)바이트 순서를 의미하고, n은 네트워크(network)바이트 순서를 의미한다.
그리고 s는 short형을 의미하고, l은 long형을 의미한다.(to는 영어 to를 뜻함)
그렇다면 이것을 가지고 위의 함수들을 해석하면 이렇게 된다.
- unsigned short htons(unsigned short); short형 데이터를 호스트바이트 순서에서 네트워크바이트 순서로 변환해라.
- unsigned short ntohs(unsigned short); short형 데이터를 네트워크바이트 순서에서 호스트바이트 순서로 변환해라.
- unsigned long htonl(unsigned long); long형 데이터를 호스트바이트 순서에서 네트워크바이트 순서로 변환해라.
- unsigned long ntohl(unsigned long); long형 데이터를 네트워크바이트 순서에서 호스트바이트 순서로 변환해라.
sockaddr_in server;
memset(&server,0,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(10000);
server.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
bind(m_hServer, (sockaddr*)&server, sizeof(server));
sockaddr_in client;
memset(&client,0,sizeof(client));
client.sin_addr.s_addr = inet_addr(IP);
client.sin_family = AF_INET;
client.sin_port = htons(Port);
connect(m_hClient, (sockaddr*)&client, sizeof(client));
여태까지 배운것들이 이 12줄을 위해 배운거랍니다. 하하하;;;
'프로그래밍 > 예전글' 카테고리의 다른 글
TCP기반의 에코서버/클라이언트 (0) | 2010.08.19 |
---|---|
리눅스 기본 명령어 (1) | 2010.08.17 |
소켓의 프로토콜 (socket함수를 파헤쳐보자) (0) | 2010.08.16 |
윈도우 기반의 소켓관련 함수 (0) | 2010.08.14 |
페도라 리눅스 GUI에서 CUI로 바꾸자~! (vi 명령어 사용) (0) | 2010.08.14 |