패딩비트를 고려한 구조체를 네트웍으로 전송하는것이 과연 portable한 방법인가요?

superkkt의 이미지

안녕하세요.

아래와 같이 패딩비트를 고려한 구조체가 있습니다.

struct {
    uint32_t a;
    uint16_t b;
    char dummy[2];
    uint32_t c;
} test;

이러한 구조체를 그대로 네트웍으로 전송하고, 수신측에서 수신한 패킷을 위 구조체로 캐스팅해서 사용하는 방법이 portable한 방법이라고 할 수 있나요? 아! 그리고 송신/수신측에서 엔디안 변환은 적절하게 해준다는 가정하에서입니다.

그리고 프로그래머가 구조체의 패딩비트를 직접 다루려고 할때, 멤버 변수 중 가장 큰 타입의 배수로 전체 구조체 크기를 맞춰주면 되는건가요? 아래는 제 블로그에 제가 이해하고 있는 메모리 정렬에 대해서 써놓은 글인데.. 아무래도 잘못 알고 있는 부분이 있는것 같습니다. 혹시 틀린 부분이 있다면 지적 부탁드립니다.

http://superkkt.com/159

원문을 여기에 인용하려고 했는데, 가독성이 많이 떨어져서 그냥 링크로 걸었습니다.

sunyzero의 이미지

TCP 나 IP 의 헤더에서도 패딩을 고려한 설계가 되어있지요.

적절한 패딩을 고려한 네트워크상의 구조체 전송이 문제가 된다고 하면
TCP/IP 자체도 문제가 있다고 하는 것과 다를바가 없습니다.

사실상 바이너리 데이터 전송에서는 어쩔 수 없는 문제죠.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

superkkt의 이미지

/usr/include/netinet 디렉토리에 있는 ip.h나 tcp.h를 보면 전혀 패딩 비트를 고려하지 않은 구조체가 있는것 같은데요. 실제로 네트웍으로 TCP/IP 패킷을 전송하는 루틴에서는 구조체를 그대로 전송하지 않고, 어떤 처리과정을 거친 후에 전송하는것이 아닌가요?

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

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

sunyzero의 이미지

reserved 된 영역들이 원래 word ordering 을 위해서 패딩을 고려한 영역입니다.
이 부분들은 넣으나 안넣으나 구조체의 크기는 같지만, 일부러 넣는 부분이죠.

네트워크 프로그래밍에서 바이너리 전송에서는 패딩을 고려해서 중간중간에 끼워넣는 부분을 넣거나
아니면 word 단위로 추려낸 뒤에 맨뒷부분에 패딩을 고려한 채워넣기를 합니다.
헤더 파일을 자세히 보세요. 중간이나 끝에 아무 의미없이 채워넣은 필드가 있습니다.

그리고 tcp/ip 책에 보면 헤더가 나오는데, 중간에 reserved 가 보이죠? 실제 구현시에 패딩을 고려한 설계입니다. 대부분 실무에서도 이런식으루 중간에 구조체에 패딩영역을 생략하지 않고, 채워넣습니다.

일반적으로 패딩을 고려한 설계에서 data, resv, reserved, fill, filler, pad, padding 의 식으로 이름을 붙이면 거의 99%는 패딩 고려 설계를 위한 부분입니다.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

doogie의 이미지

가장 많이 쓰는 방법이라고 생각이 드는데요

CRC 체크섬을 넣는 것이 어떨까 싶네요
해당 구조체만큼의 패킷을 읽어서 구조체로 캐스팅한 후에
체크섬을 계산한 후 구조체내의 체크섬과 비교하면 될 듯 싶습니다 ^^

CRC 체크섬 소스는 구글신한테 물어보시면 바로 응답을 해준다죠 ^^
아니면 구글 codesearch로 검색을 하셔도 됩니다 ^^

언제나 처음처럼 ~~

언제나 처음처럼 ~~

doogie의 이미지

제 답글이 핀트가 약간 벗어났네요...
삭제가 안되서 이렇게 적습니다 -_-;;

언제나 처음처럼 ~~

언제나 처음처럼 ~~

chadr의 이미지

패딩을 넣든 안넣든간에 send 함수 호출시 넣어주는 바이트수만 정확히 구조체의
실제 바이트수하고 일치만 한다면 문제가 없을듯 합니다..
물론 바이트 오더를 맞췄다는 가정하에서요.. :)
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

superkkt의 이미지

아.. 제가 질문에 미리 얘기를 안했는데.. 이기종간에 구조체를 전송하는걸 얘기하는거였습니다. 만약 시스템 A와 시스템 B가 구조체에 패딩을 삽입하는 방식이 서로 다르다면 패딩 비트를 고려해서 구조체를 만들지 않는 경우 서로 다르게 구조체를 해석하는 문제가 생기겠죠.

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

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

sunyzero의 이미지

궁금해 하시는 부분이 XDR인것 같네요.

? RFC 1832, XDR: External Data Representation Standard

========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

superkkt의 이미지

네, RFC 문서를 읽어봤습니다. 그런데 이미 코딩이 너무 많이 진행이 되어서 지금 XDR을 적용시키기는 힘든 상황입니다. 현재 코드를 이기종 장비간에서 테스트를 해본 결과는 별 문제가 없는것 같은데, 개인적으로 이런 방법이 full portablity를 가지는지 궁금해서 질문을 올린것입니다.

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

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

sunyzero의 이미지

감당할 수 있다면 XDR 을 적용하는게 좋고,
만일 감당할 수 없는 만큼 진행되었다면 조용히 덮어야죠. -_-;;
괜히 건드려서 들쑤시면 인간관계가 나빠질 수도...

사실 XDR 을 적용하지 않았다면 분명 다른 플랫폼으로 이전하거나
java 나 다른 언어로 짜여진 시스템과 통신할때 분명 문제의 소지는 있지요.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

chadr의 이미지

처음부터 패딩비트를 넣지 않으면 어떨까요?
아래와 같은 전처리기문으로요..

#pragma pack(1)
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

superkkt의 이미지

#pragma pack을 사용하는 방법은 표준에의해 보장되는 방법이 아니라고 들었습니다. 그래서 pragma의 사용은 고려하고 있지 않습니다.

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

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

bushi의 이미지

네트웍이나 storage 등을 통해서 정보를 교환할 때는 pad+캐스팅 이나 pack+캐스팅 이나 별 차이 없을 거라 생각합니다. 둘 모두 사용해선 안 되는 방법들입니다.

말이 좀 이상한데...
이식성 좋게 코드를 만들어 놓으면 확장성이 기가막히게 떨어지면서 코드가 지저분해지는 경우가 바로 이거겠죠. 자료구조가 조금만 변해도 속상합니다.
그래도 어쩔 수 없습니다. 제가 이때까지 본 코드들도... 이부분은 항상 지저분했었습니다. 엔디안 처리까지 들어가야 하므로 나름대로 잔머리들은 많이 굴립니다.

더 늦기전에 고치시는게 좋겠습니다. byte 단위로 처리하도록요.

superkkt의 이미지

C99 문서를 찾아봤는데 구조체 부분에 아래와 같은 문장이 있더군요.

Each non-bit-field member of a structure or union object is aligned in an implementation defined manner appropriate to its type.

그럼 아주 희귀한 구현체에는 구조체의 모든 멤버가 char 타입이라고 하더라도 padding이 삽입될 가능성도 있다는 건가요? 만약 그렇다면 진정한 full portability를 얻으러면 네트웍으로 전송되는 패킷을 작성할때 모든 멤버가 char 형태인 구조체도 사용하지 못하고 아래와 같이 지저분한(?) 코드를 사용해야만 하는걸까요?

#define HEADER_SIZE 9
 
typedef struct {
    uint32_t id;
    uint8_t type;
    uint32_t value;
} header_t;
 
unsigned char *
create_header(header_t *hdr)
{
    unsigned char *ptr = NULL;
    uint32_t *id = NULL;
    uint8_t *type = NULL;
    uint32_t *value = NULL;
 
    ptr = malloc(HEADER_SIZE);
    id = (uint32_t *) ptr;
    type = (uint8_t *) (ptr + 4);
    value = (uint32_t *) (ptr + 5);
 
    *id = htonl(hdr->id);
    *type = hdr->type;
    *value = htonl(hdr->value);
 
    return ptr;
}

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

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

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.