structured data의 통신은 어떻게 하나요 ?

sirang의 이미지

안녕하세요.

socket으로 통신할때, 기본적으로 character의 stream을 주고 받는데요,
만약
struct my_data {
int a;
int b;
}
위와같은 structure를 주고 받고 싶으면 어떻게 해야 하는거죠 ?

읽는 함수는 read()를 이용할 생각이구요.

제가 생각하고 있는 것은 다음과 같습니다.

char buf[MAX];
struct my_data * my;
read(fd, buf, MAX);
my = (struct my_data*)buf;

이렇게 하고나서 아래와 같이 사용할 수 있는 건가요 ?
tmpa = my->a;
tmpb = my->b;

혹시 network byte order 등의 문제로 이렇게 하면 문제가 생기는지요 ?

아니면 또다른 방법이 있나요 ?

많은 조언 부탁드립니다.

danielkim의 이미지

통신을 할 양 MACHINE의 OS외 기계적인 환경이 동일하다면
올리신 코드는 우선 운용되는 대는 문제가 없을 수 있습니다.
하지만 서버와 CLIENT가 OS가 틀린다든지 하면 문제가 발생합니다.

INTEGER LONG등을 송수신하시기 전에 아래의 함수를 이용해서
변경해서 설정하시면 됩니다.

      unsigned long int htonl(unsigned long int hostlong);

       unsigned short int htons(unsigned short int hostshort);

       unsigned long int ntohl(unsigned long int netlong);

       unsigned short int ntohs(unsigned short int netshort);
lunarainbow의 이미지

sirang wrote:

struct my_data {
int a;
int b;
}

char buf[MAX];
struct my_data * my;
read(fd, buf, MAX);
my = (struct my_data*)buf;

이렇게 하고나서 아래와 같이 사용할 수 있는 건가요 ?
tmpa = my->a;
tmpb = my->b;

굳이 이렇게 할 필요 없으신듯 싶은데..

struct my_data Data;

read(fd, (char*)Data, MAX);

tmpa = Data->a;
tmpb = Data->b;

바이트 오더만 danielkim 님이 말씀하신대로 해결해 주신다면, 이렇게 해주시는게 약간 더 편하지 않을까 싶은데.. ^^

raymundo의 이미지

지금 같은 경우는 a 와 b 가 같은 int 형이지만, 만일 a 가 short 나 char 이면

struct {
    short int a;
    int b;
}

이게 실제 메모리에서 6 바이트 (a 2 + b 4) 를 차지할지, 8 바이트 (a 2 + padding 2 + b 4) 를 차지할지는 아키텍춰에 따라 다른 걸로 알고 있습니다.

그렇다면 단순히 char * 로 변환해서 보내고 받은 후 data->a data->b 와 같은 식으로 접근하는 것이 문제가 될 수 있지 않을까요?

(제가 정확히 아는 것이 아니라서... 틀리면 지적 바랍니다)

좋은 하루 되세요!

최병현의 이미지

danielkim wrote:
통신을 할 양 MACHINE의 OS외 기계적인 환경이 동일하다면
올리신 코드는 우선 운용되는 대는 문제가 없을 수 있습니다.
하지만 서버와 CLIENT가 OS가 틀린다든지 하면 문제가 발생합니다.

danielkim님께서 말씀하신 것처럼 이기종간 통신에서는 structure를 바로 보낼 경우는 padding에 의한 문제가 발생할 수 있다고 합니다.

이와 비슷한 일을 전에 해본적이 있습니다만,
Linux(intel cpu) <---> window(intel cpu)는 아무런 문제가 없었습니다.
window(intel cpu) <----> HP-UX11은 integer의 경우 byte ordering문제가 생겼습니다. (예상은 하고 있었습니다. :wink: )

To be a rich

danielkim의 이미지

raymundo님의 글에 추가로 사족을 달고자 합니다.
말씀하신대로 struct 형태의 데이타 타입을 compile해서 sizeof 해 보면
compiler에 설정된 byte-alignment option 에 따라 크기가 달라지는
것이 맞습니다. (현재 팬티엄 cpu를 채용한 os의 경우 4-byte alignment가 default상태입니다)
따라서 해결하려면 이를 해결하려면 두가지 방법이 있습니다.
1. integer, long 등을 ascii 문자열로 구성되도록 프로토콜을 설계한다.

2. compile 시 1-byte alignment로 설정한다.
(이경우 프로그램의 처리 속도를 trade-off 해야하는 단점이 있습니다)

도움 되시길 바랍니다.

choissi의 이미지

lunarainbow wrote:
sirang wrote:

struct my_data {
int a;
int b;
}

char buf[MAX];
struct my_data * my;
read(fd, buf, MAX);
my = (struct my_data*)buf;

이렇게 하고나서 아래와 같이 사용할 수 있는 건가요 ?
tmpa = my->a;
tmpb = my->b;

굳이 이렇게 할 필요 없으신듯 싶은데..

struct my_data Data;

read(fd, (char*)Data, MAX);

tmpa = Data->a;
tmpb = Data->b;

바이트 오더만 danielkim 님이 말씀하신대로 해결해 주신다면, 이렇게 해주시는게 약간 더 편하지 않을까 싶은데.. ^^

오류가 있네요

Quote:
struct my_data Data;

read(fd, (char*)&Data, MAX);

tmpa = Data.a;
tmpb = Data.b;

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

lunarainbow의 이미지

choissi wrote:
오류가 있네요

Quote:
struct my_data Data;

read(fd, (char*)&Data, MAX);

tmpa = Data.a;
tmpb = Data.b;

크~ 이런 실수를.. :?

sirang의 이미지

답변 감사합니다.

그런데 danielkim 님께서 아래와 같이 말씀하셨는데요.

Quote:

1. integer, long 등을 ascii 문자열로 구성되도록 프로토콜을 설계한다.

2. compile 시 1-byte alignment로 설정한다.
(이경우 프로그램의 처리 속도를 trade-off 해야하는 단점이 있습니다)

1, 2 에 대해서 좀 더 자세히 설명해주실수 있을까요 ?

김충길의 이미지

sirang wrote:
답변 감사합니다.

그런데 danielkim 님께서 아래와 같이 말씀하셨는데요.

Quote:

1. integer, long 등을 ascii 문자열로 구성되도록 프로토콜을 설계한다.

2. compile 시 1-byte alignment로 설정한다.
(이경우 프로그램의 처리 속도를 trade-off 해야하는 단점이 있습니다)

1, 2 에 대해서 좀 더 자세히 설명해주실수 있을까요 ?

예를 들어 { 12, 655357 } 이라는 데이타를 보내기 위해서 12|655357 이렇게
문자열 형태로 보낸다는 말 같습니다. | 문자는 둘 사이의 구분자로 사용하고요
문자열로 할 경우 보낼 데이타가 약간 길어지는 단점이 있지만 이 단점을 극복
하고도 남을 이기종간의 복잡도는 생각 안해도 되죠(또 단점은 문자열 -> 내부 타입으로 변화. 12라는 문자열을 변환하기 위해 atoi 같은 함수를 사용해야
한다는 거죠).

인터넷 프로토콜들은 대부분 문자열 기반이 많죠. HTTP

screen + vim + ctags 좋아요~

danielkim의 이미지

질의하신 내용에 추가적으로 답변을 올리니 참고 하시기바랍니다.


struct my_data { 
int a; 
int b; 
} 

// 프로토콜내에서 정의된 형식 
//      통상 4 byte alignment에 맞도록 설계하시는게  복잡한 문제들을
//      피해 갈수 있는 방법입니다. 
struct str_my_data{
       char  strIntA[12];
       char strIntB[12];
}

struct my_data  m_data;
struct str_my_data  str_m_data;

            //1.  Network에서 data를 읽은후 내부 처리용으로 변경하는 경우 
            m_data.a = atoi(str_m_data.strIntA);

            //2. 내부 처리용 data를 network용으로 변경하는 경우 
           //    itoa 라는 함수는 없습니다. 만드셔야 되고요
          //     이름에서 알수 있듯이 integer를 문자열로 변경하는 거겠지요
           strcpy(str_mdata.strIntA, itoa(m_data.a));


도움되시길 바랍니다.

댓글 달기

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