endian에 따른 서버 프로그램 변경

choco6의 이미지

미션 크리티컬한 업무의 서버 프로그램을 담당하고 있습니다.
현재까지 운영중인 서버 플랫폼이 HP Alpha서버였는데 little-endian인 알파칩 CPU이고 client 장비도 x86 계열의 CPU를 사용하고 있어서 그동안 통신하는데는 문제가 없었습니다.
그런데 문제는 서버를 곧 교체할 예정인데 교체될 서버는 HP PA RISC 를 채용하고 있는 CPU이고 이게 big-endian 체계라는 겁니다. 그래서 서버 프로그램에서 보내는 데이타 구조가 소켓을 통해 client로 넘어갈 때 int나 short등의 정수 데이타가 몽땅 뒤집혀서 전달됩니다.
그런데 이런 서버와 client가 주고받는 통신 구조체가 꽤 양이 많은데 이 구조체에서 정의하는 정수 데이타 필드를 하나 하나 htons()로 바꾸어주어야 하는건지.... 이렇게 필드 하나 하나를 변환한다는게 정말 장난이 아닌데 한숨이 나오네요..
혹시 저와 비슷한 처지의 상황에 계셨던 분중에서 좀더 우아한 방식으로 엔디안 체계를 해결하신 분이 계신지요. 조언 부탁합니다.

lacovnk의 이미지

음.. 서버 프로그래밍에서는 network order로 커버하지 않나요?

http://www.aquaphoenix.com/ref/gnu_c_library/libc_194.html

http://home.lacovnk.net/

choco6의 이미지

저의 질문은 network order로 변환하는 함수를 물은 것이 아닙니다.
제 질문의 취지를 좀더 자세히 설명드리면,
만약, 서버에서 클라이언트로 다음과 같은 구조체를 보낸다고 합시다.

struct _info_head {
int head_id;
char file_name[25];
int file_size;
short magic;
int packet_size;
};

만약 서버가 big-endian 체계이고 클라이언트가 little-endian 체계라면, 위의 구조체를 채우고 클라이언트로 보낸다면 head_id, file_size, magic등의 데이타가 몽땅 뒤집혀서 클라이언트 프로그램이 잘못 해석하게 됩니다.
그럼 방법은 int, short등으로 정의된 데이타 필드를 하나 하나 htons로 교환해야 합니다.

struct _info_head data;
...
data.head_id = ntons(data.head_id);
data.file_size = ntons(data.file_size);
...

이렇게 하면, 서버에서 클라이언트로 보내는 모든 데이타 구조의 필드 하나 하나를 위와 같이 컨버전을 해야하는데... 통신 데이타 구조가 많을 경우 이런 작업이 장난이 아니게 커집니다..
그래서 좀더 우아한 방법이 없는지 알아보려는 것입니다.
혹시 저와 비슷한 경험이 있으신 분들이 있나요?

kslee80의 이미지

처음에 통신 프로토콜을 설계할 때 endian 에 영향을 받지 않는 형태로 설계하지 않는한은
그런 동작은 항상 수행되어야 합니다 ;;

지금까지는 서버-클라이언트 둘 다 little-endian 이기 때문에 아무런 문제가 없었겠지만,
데이터를 바이너리 형태로 전송할때는 항상 byte order 조정을 하는 것이 정상입니다.
보통은 전송시에는 big-endian 형태로 조정하고,
받는 쪽에서는 big-endian 형태의 데이터를 자신의 native order 에 맞춰서 읽어들이는 형식으로 하죠.
항상 이렇지는 않지만 말이죠. 위의 경우는 서버와 클라이언트 둘 다 어떠한 byte order 를 가지는 machine 에서도 동작하여야 한다면 취하게 되는 방식이며,
client 가 항상 x86 이라거나 하는 조건이 있다면 서버단에서는 little-endian 으로 전송하고, client 는 그냥 읽어들이는 식으로 작성하는것이 더 낫겠죠.

우아하지는 않지만 모든 데이터 구조의 필드 하나하나를 다 endian 조정을 해서 전송하는 식으로 프로그램을 수정하셔야 할 것입니다.
미션-크리티컬 하다고 말씀하셨으니, 지금와서 프로토콜을 endian 에 영향을 받지 않게 다시 설계하는 것은 해결법이 아닌것으로 보입니다.

choco6의 이미지

kslee80 님 답변 감사합니다..
역시... 지름길은 없었네요... 예상은 하고 있었지만...ㅠㅠ
애초에 설계할 당시 byte order에 의존적이지 않게 설계를 했어야 하는데.. 뒤늦게 난리를 치게되었군요.
앞으로 어떻게 작업해야할지 한숨이 나오네요.. ㅠㅠ

superkkt의 이미지

byte order에 영향을 받지 않도록 작성하는 방법은 어떤게 있나요? 정수형을 사용하지 않고 모든 숫자를 문자열로 처리하는 방법인가요?

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

IDNed의 이미지

그게 아니라 모든 엔디안 의존적인 정수형을 하나로(네트워크 바이트 오더) 통일 후 서버/클라이언트에서 이를 자신에게 맞는 바이트 오더로 변환하는 게 가장 좋을듯...

kslee80의 이미지

데이터 처리를 몽땅 다 String 으로 하는 방법도 하나의 방법이죠..
그리고 데이터중에 정수형의 크기가 크지 않다면, 정수형을 1byte 로 표현하는 방식을 써도 byte order 에 영향을 받지 않는 프로토콜이 되겠죠.

요즘은 Byte order 에 영향받지 않기 위해서 통신 프로토콜을 XML 로 쓰죠.
대표적인 녀석이 WebService 구요..
(WebService 의 하위 통신프로토콜인 SOAP 은 XML 이죠.)

XML 이 등장하기 이전에 많이 쓰이던 방식은 XDR 이고..
(XDR = IETF RFC 1014)
NFS 와 RPC 가 이 방식을 쓰죠.

lacovnk의 이미지

바이트 오더 뿐만 아니라, 패딩 같은 건 문제가 안되나요?

http://home.lacovnk.net/

IDNed의 이미지

패딩은 구조체쪽 문제 아닌가요?
#pragma를 쓰거나(비표준일껄요) 아니면 멤버를 일일히 소켓으로 보내는 게 나을 것 같은데... 성능상...

사이 패딩까지 보낼 필요는 없으니까요. ;)

sandro의 이미지

배열로 보내는게 더 유연할겁니다.

無心

Anonymou의 이미지

구조체라는 메모리상의 데이타를 그대로 보낸다는 건데 좋은 방법이 아닙니다.

애초에 구조체 보내기를 배제하고 보내는걸로 잡았어야 했다고 생각됩니다.

C/S 구조라면 플랫폼 의존적인 부분은 항상 고려해야 합니다.

대부분의 internet 프로토콜을 보면 그런 부분을 배제하지요.
예를 들어 http, telnet, ftp 등등

shji의 이미지

위와 같이 Endian이나 Padding의 문제가 항상 있으므로
프로그램간 통신 프로그래밍을 할 때는 구조체를 사용하지
않고 있습니다.

대신 패킷 전송을 위한 배열을 하나 잡아 놓고 여기에
원하는 구조체를 배열에 탑재하는 함수를 각각의 경우에
만들어 두고 사용합니다.

Endian 문제는 이 함수에서 배열에 구조체의 각 요소를
넣을 때 Endian 처리 함수를 불러 해결하도록 하구요..

처음 작성할 때는 번거롭고 또 구조체를 통으로 사용하는
것보다 버그의 존재 확률이 높지만(타이핑 실수 등..)
이기종 혹은 다른 환경(컴파일러 등)끼리를 전제로 하는 경우에는
구조체를 피하는 것이 저의 방법입니다..^^

제 주위의 윈도우즈 어플리케이션을 작성하시는 분들은 구조체를
그냥 전달하는 방법을 애용하시는데 제 방법을 말씀드리면
상당히 어려워하시더라구요.. (난이도가 높다는 게 아니라 적용하기가
꺼려진단... ^^;)

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.