htonl , ntohl에 대한 질문입니다.
안녕하세요
열심히 프로젝트를 하는 사람입니다.
오늘 인디언 문제로 갑자기 골머리를 앓아서 질문을 드립니다.
책에서는 (윤성우저(TCP&IP소켓 프로그래밍)htonl과 ntohl에 대해
htonl host byte to network byte순으로 바꿔준다
ntohl network byte to host byte 순으로 바꿔준다
라고 나와있습니다.
프로젝트를 하면서 #ifdef 를 사용해서 빅인디언일때와 리틀인디언일때를 각각 나눠서 변형을 시켰습니다.
(통신은 빅으로 맞춰준다란 부분이 있다곤 알고 있지만 서버에 맞추란 상관의 지시에따라..)
ex)
a = 2;
#ifdef BIG
a = htonl(a);
#endif
#ifdef LITTLE
a = ntohl(a);
#endif
그런데 실험중에 클라이언트가 리틀이고 서버가 빅일때 -DBIG을 주던지 -DLITTLE을 주던지 통신이 됩니다.
ntohl이나 htonl이나 모두다 자신의 인디언체계를 반대되는 인디언 체계로 바꿔주는 동작을 하더군요..
결국 서버랑 인디언체계가 반대된다면 두개 함수중 아무거나 사용해도 된다.. 호스트바이트를 네트워크 바이트로 바꾸는게 아니라 그냥 바꾸는게 되는거 같습니다.
함수를 다르게 놓은건 구분인거 같구요..
a = 2;
#ifdef ENDIANCH
a = htonl(a);
#endif
현재는 이런형태로 바꿨습니다. 인디언이 다를경우 컴파일때 -DENDIANCH를 하라..
제가 보기엔 두함수가 동작이 똑같고 인디언이 다를때만 아무가나 호출해도 될꺼같습니다.
제가 틀리거나 모르는 사항이 있으면 지도 부탁드립니다..
잘못하면 프로젝트가 큰일나서..
아래는 실험 내용과 결과 입니다.
======================
실험
======================
int main(void)
{
int i, big,litte,big2, litte2;
i = 0x12345678;
big = htonl(i);
litthe = ntohl(i);
big2 = ntohl(big);
litthe2 = htonl(litthe);
printf("big[%x]\n",big);
printf("little[%x]\n",litthe);
printf("big[%x]\n",big2);
printf("little[%x]\n",litthe2);
}
big[78563412]
little[78563412]
big[12345678]
little[12345678]
==========================================
Big endian host에서는 위
Big endian host에서는 위 함수는 아무런 동작을 하지 않습니다.
Little endian host에서 두 함수는 똑같이 endian을 뒤집는 같은 동작을 합니다.
다만 해당 인자나 반환값이 어떤 의미를 지니는지에 따라 함수를 다르게 사용하는 것이 코드 가독성을 높일 수 있습니다.
따라서 컨벤션을 따른다면, 서버가 little endian이라고 해서 네트워크 패킷을 little endian으로 보낸다면 상당히 불편할 수 있지요. (위에 서버에 맞춘다는 얘기가 어떤 얘기인지는 모르겠습니다마는)
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net
귀중한 답변 감사합니다.
서버에 맞춘다는 말은 님이 지적하신대로 서버가 little endian 일때 little endian으로 패킷을 보낸다는 의미입니다.
빅인디언 시스템에서 해보니까 전혀 반응이 없네요 그렇다면 서버 시스템에 맞춰서 인디언 시스템을 바꿔줄수 없다는 말인거 같네요
만약 그런데도 바꿔라고 한다면 정말 나쁜 상사인거네요-_-;;
강제로 바꿔주시면 될듯...
귀찮지만...하라면 해야죠...
대부분은 정책을 정하죠. 통신은 무조건 리틀 또는 빅. 그것에 맞추어 알아서 변환.
이런식인데...어짜피 바이트 단위의 연산은 의미가 없고, 2byte, 4byte에 맞는
함수 하나 만드세요.
-------------
포탈이는 불사신
-------------
포탈이는 불사신
하라면 해야겠지만
쉽사리 생각은 안떠오르네요 어떻게 서로 위치를바꿔줘야 할지
빅과 리틀이 어떤순서로 되는지는 알고 있지만 바이트 단위에 수가 들어있는걸 카피해서 위치를 옮긴다..
쉽사리 아이디어는 안떠오르네요..하라고 한다면 업무가 안그래도 밀려있는데...몇일밤은 새야겠네요
대충 이런 식?
함수의 인자타입은 POSIX기준을 따랐습니다. uint16_t 같은 것은 linux에서는 stdint.h에서 가져와서 썼는데 썬 장비에서는 해당 헤더 파일이 없었던 것으로 기억합니다. inttypes.h가 대충 공통 헤더로 사용이 가능한 것 같더군요. 기본으로 제공하는 함수가 4비트까지만 있어서 8비트 숫자를 변환하기 위해 만든 적이 있던 것을 조금 수정해 봤습니다.
댓글 적으면서 생각났는데 swap함수로 매번 ifdef처리하는 것 보다는 그냥 to_server_endian같은 이름의 함수를 포인터 형식으로 만들어서 적절하게 엔디안 지정하는 것도 한 방법일 듯 합니다.
=================
잠못자는 한솔아빠
=================
잠못자는 한솔아빠
답변 감사합니다.
일단 다른 업무를 우선봐야해서 직접 실행은 못해봤지만
답변 너무 감사드립니다.
차후에 실행시 질문사항이 생기면 다시 문의를 좀 드리겠습니다.
즐거운 하루되세요^^
응?
제가 제대로 이해했는지 모르겠는데요.
예를들어 ntohl() 일경우... 이 함수 자체가 network > BIG / host > LITTLE 로 가정하고 바꾸는 거 아닌가요? 즉, 함수 자체에 네트웤 / 호스트가 BIG/LITTLE중 어떤 걸 쓰고 있는지는 판단하지 않는다...
이렇게 알고 있는데요. 틀린 건가요?
(실제로 다른 환경에서 실험해 본 적은 없..-_-;;)
행복은 희생없이는 얻을 수 없는 것인가?
시대는 불행없이는 넘을 수 없는 것인가?
네
호스트의 byte order에 따라 판단합니다.
glibc의 netinet/in.h를 보면
이런 코드가 있죠.
아....그렇군요.
몰랐네요.
답변 감사합니다.
행복은 희생없이는 얻을 수 없는 것인가?
시대는 불행없이는 넘을 수 없는 것인가?
댓글 달기