Summry
데이터는 바이트 단위로 저장되지만 저장되는 방식에 있어서 CPU마다 차이가 발생하게 된다. 예를 들어 4바이트 크기의 int자료를 저장한다고 했을 때 어떤 CPU는 가장 낮은 바이트부터 저장을 하는가 하면, 어떤 CPU는 가장 높은 바이트 부터 데이터를 저장하기도 한다. 전자를 Little Endian방식, 후자를 Big Endian방식 이라고 한다.
이런 이유로 서로 다른 데이터 저장 방식을 사용하는 시스템끼리 통신을 하게 될경우 전혀 원하지 않는 값들을 서로 주고 받는 경우가 발생할 수 있다. 한쪽에서는 12345를 보냈는데, 다른 한쪽에서는 엉뚱하게 365779719로 받아 들이는 문제들이 발생한다.
이런 문제를 해결하기 위해서 데이터 통신을 할때는 명시적으로 네트워크 byte order을 따르도록 데이터의 byte order를 변경한다. 네트워크 byte order는 Big Endiasn을 따른다.
원격 호스트와 데이터 통신을 하길 원한다면 보낼 때 네트워크 byte order로, 받았을 때는 호스트 byte order로 변경한다.
본 문서에서는 byte oder를 변경해주는 함수들을 정리한다.
send me email if you have any questions.
htons()
#include <netinet/in.h>
unsigned short int htons(unsigned short int hostshort);
htons()함수는 short intger(일반적으로 2byte)데이터를 네트워크 byte order로 변경한다.
htonl()
#include <netinet/in.h>
unsigned long int htonl(unsigned long int hostshort);
htonl()함수는 long intger(일반적으로 4byte)데이터를 네트워크 byte order로 변경한다.
ntohl()
#include <netinet/in.h>
unsigned long int ntohl(unsigned long int hostshort);
ntohl()함수는 long intger 데이터를 호스트 byte order로 변경한다.
ntohs()
#include <netinet/in.h>
unsigned short int ntohs(unsigned short int hostshort);
ntohs()함수는 short intger 데이터를 호스트 byte order로 변경한다.
return
네트워크 byte order된 2바이트 값을 넘겨준다.
example code
#include <sys/time.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char **argv)
{
int client_sockfd;
struct sockaddr_in clientaddr;
int data = 123456789;
int client_len;
client_sockfd = socket(AF_INET, SOCK_STREAM, 0);
clientaddr.sin_family = AF_INET;
clientaddr.sin_addr.s_addr = inet_addr("192.168.100.190");
clientaddr.sin_port = htons(atoi(argv[1]));
client_len = sizeof(clientaddr);
if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) < 0)
{
perror("Connect error : ");
exit(0);
}
// 보낼 데이터 네트워크 byte order를 따르도록 변경한다.
data = htonl(data);
write(client_sockfd, (void *)&data, sizeof(int));
// 읽어들인 데이터는 호스트 byte order을 따르도록 변경한다.
read(client_sockfd, (void *)&data, sizeof(int));
data = ntohl(data);
close(client_sockfd);
}