IP 주소 변환 함수 설명 전 이해하자!
예) 0x12345678 4바이트 데이터가 있다.
이 데이터가 메모리에 저장될 때 하위 바이트/ 상위 바이트가 저장되는 메모리 주소는 어떻게 될까?
1. 빅 에디안(Big-Endian)
- 하위 바이트가 저장되는 주소가 상위 바이트가 저장되는 주소보다 큰 경우
0x12 - 1바이트 ➡️ 0x107번지
0x34 - 1바이트 ➡️ 0x108번지
0x56 - 1바이트 ➡️ 0x109번지
0x78 - 1바이트 ➡️ 0x110번지
2. 리틀 엔디안(Little-endian)
- 하위 바이트가 저장되는 주소가 상위 바이트가 저장되는 주소보다 작은 경우
0x12 - 1바이트 ➡️ 0x110번지
0x34 - 1바이트 ➡️ 0x109번지
0x56 - 1바이트 ➡️ 0x108번지
0x78 - 1바이트 ➡️ 0x107번지
3. 호스트 바이트 순서 VS 네트워크 바이트 순서
- 바이트 순서는 해당하는 OS 시스템이 내부적으로 데이터를 표현하는 방법
3-1. 호스트 바이트 순서
- 시스템의 CPU에 따라 빅 에디안 방식을 쓸지 리틀 에디안 방식을 쓸지 결정
⚠️ 서로 다른 방식을 사용하는 CPU 간 데이터 교환을 할 경우 문제가 생김 ⚠️
3-2. 네트워크 바이트 순서
- 빅 에디안 방식만을 사용
4. 바이트 순서 변환 함수 종류
htonl: 호스트 바이트 순서 ➡️ 네트워크 바이트 순서 long
htons: 호스트 바이트 순서 ➡️ 네트워크 바이트 순서 short
ntohl: 네트워크 바이트 순서 ➡️ 호스트 바이트 순서 long
ntohs: 네트워크 바이트 순서 ➡️ 호스트 바이트 순서 short
문자열 IP ➡️ 네트워크 바이트 순서
1. inet_addr
- 문자열 IP 주소 ➡️ 네트워크 바이트 순서
- 성공시 32비트 정수값 / 실패 시 INADDR_NONE
- 주로 코더들이 쓰는 함수(구조체안에 변환해서 다시 구조체 대입)
serv_addr.sin_addr.s_addr = inet_addr(serv_ip);
2. inet_network
- 문자열 IP 주소 ➡️ 호스트 바이트 순서 ➕ ➡️네트워크 바이트 주소
serv_addr.sin_addr.s_addr = htonl(inet_network(serv_ip));
3. inet_aton
- 문자열 IP 주소 ➡️ 네트워크 바이트 주소(IN_ADDR 주소에 맞게 변환)
- 성공시 1(true) / 실패 시 0(false)
- 주로 많이 사용(변환시키면서 동시에 대입)
inet_aton(serv_ip, &serv_addr.sin_addr);
4. inet_pton
- 특정 형식에 상관없이 변환 🟰 입력 값이 많다는 것을 의미
- 프로토콜 선택
inet_pton(AF_INET, serv_ip, &serv_addr.sin_addr.s_addr);
네트워크 바이트 순서 ➡️ 문자열 IP
1. inet_ntoa
- INADDR 구조체 주소 ➡️ 문자열 IP 주소
- 성공 시 변환한 문자 주소 값 / 실패 시 -1
char* str_ptr = inet_ntoa(serv_addr.sin_addr)
2. inet_ntop
- 프로토콜 선택
- 임의 형식으로 된 주소 ➡️ 문자열 IP 주소
전체 소스 코드
#include <cstdio>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <memory.h>
int main()
{
int serv_sock;
struct sockaddr_in serv_addr;
char* serv_ip = "127.0.0.1";
char* serv_port = "8080";
serv_sock = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == serv_scok) {
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
// 프로토콜 값 입력
serv_addr.sin_family = AF_INET;
//문자열 port 값 입력 => 2바이트짜리 숫자로 변경 => 네트워크 바이트로 변경
serv_addr.sin_port = htons(atoi(serv_port));
// 문자열 ip 값 입력 => 바이트 주소로 변환하여 입력
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* -----------------------------------------------------------
그 외의 다양한 ip 값 입력 방법
-----------------------------------------------------------
1) inet_addr: 문자열 => 4바이트짜리 네트워크 바이트 주소로 변경
serv_addr.sin_addr.s_addr = inet_addr(serv_ip);
2) htonl: 문자열 => 호스트 바이트 주소 => 네트워크 바이트 주소
serv_addr.sin_addr.s_addr = htonl(inet_network(serv_ip));
3) inet_aton: 문자열 => 네트워크 바이트 주소
inet_aton(serv_ip, &serv_addr.sin_addr);
4) inet_pton: 문자열 => 네트워크 바이트 주소
inet_pton(AF_INET, serv_ip, &serv_addr.sin_addr.s_addr);
----------------------------------------------------------- */
printf("Network Ordered Addr: %lx\n", serv_addr.sin_addr.s_addr);
// 네트워크 바이트 주소 => 문자열 IP 주소
printf("Dotted Decimal IP Addr : %s\n", inet_ntoa(serv_addr.sin_addr));
return 0;
}
'Network > Socket' 카테고리의 다른 글
[Linux Socket] Server - Listen() 함수/ Accept() 함수[3] (0) | 2023.05.11 |
---|---|
🔖SOCKADDR VS SOCKADDR_IN (0) | 2023.05.09 |
[Linux Socket] Server - bind() 함수[2] (0) | 2023.05.04 |
🔖 SOCK_STREAM VS SOCK_DGAM (0) | 2023.05.04 |
[Linux Socket] Server - socket() 함수[1] (0) | 2023.05.03 |