소켓이나 파일을 통해 읽어들인 데이터를 구조체에 한꺼번에 넣

kornet의 이미지

안녕하세요.

소켓이나 파일을 통해 데이터를 읽어들였는데, 그 데이터를 읽어들이는 과정이 비동기적으로 이루어지는지라 하나씩 처리하기 귀찮아서(^^;) 한꺼번에 읽어들였습니다.

이때 char* buf 에 모든 데이터가 들어가있고, 그 앞부분에 다음과 같은 구조체로 되어있습니다.

<code>
struct packetType {
unsigned int nTotalLength;
unsigned int nHeaderLength;
unsigned char nProtocolVersion;
char pcGameCode[3];
unsigned char nGameVersion;
unsigned int nCommand;
};
</code>

이것을 그냥 구조체로 캐스팅하면 바이트 정렬 문제로 인하여 데이터가 상하죠. ㅡㅡ;

1바이트씩 읽어서 빅엔디안/리틀엔디안 시스템에 따라 비트쉬프트를 하여 2/4바이트의 값으로 조합하는 것도 생각해봤지만,

무언가 더 좋은 방법이 있을 것 같은데.. 어떻게 하면 깔끔하게 처리될까요?

고수님들의 조언을 부탁드립니다 ^^

송지석의 이미지

ntohl을 사용해보심이...
함수를 만들어놓고 변환하시는 게 어떨까하는데요...
읽는 것은 네트웍 오더일 것이고 사용하기는 호스트 바이트오더니까요.
저장할 때는 htonl로 하시고요.

BYTEORDER(3)        Linux Programmer's Manual        BYTEORDER(3)

NAME
       htonl,  htons,  ntohl, ntohs - convert values between host
       and network byte order

SYNOPSIS
       #include <netinet/in.h>

       uint32_t htonl(uint32_t hostlong);

       uint16_t htons(uint16_t hostshort);

       uint32_t ntohl(uint32_t netlong);

       uint16_t ntohs(uint16_t netshort);

DESCRIPTION
       The htonl() function converts the unsigned  integer  host-
       long from host byte order to network byte order.

       The  htons()  function converts the unsigned short integer
       hostshort from host byte order to network byte order.
kornet의 이미지

제가 실수를 했네요. ^^;

바이트 오더가 아니라 구조체 멤버 정렬 문제였어요.

구조체 패딩 문제없이 어떻게 하면 저것을 깔끔하게 메모리상의 구조체로 옮길 수 있을까요?

pynoos의 이미지

만약 C++ 이라면 다음과 같이 해결할 수 있겠지요...
C 라면.. 뭐.. 별수 없슴다..

struct packetType { 
unsigned int nTotalLength; 
unsigned int nHeaderLength; 
unsigned char nProtocolVersion; 
char pcGameCode[3]; 
unsigned char nGameVersion; 
unsigned int nCommand; 
}; 

unsigned long 이라고 가정하고 하겠습니다..

#include <netinet/in.h>
class NLong
{
public:
        unsigned long data;
        operator unsigned long () const 
        {       
                return (unsigned long) ntohl(data);
        }       

        NLong & operator= ( unsigned long rhs ) 
        {       
                data = (unsigned long) htonl(rhs); 
                return *this;
        }       
};

struct packetType { 
NLong nTotalLength; 
NLong nHeaderLength; 
unsigned char nProtocolVersion; 
char pcGameCode[3]; 
unsigned char nGameVersion; 
NLong nCommand; 
}; 

packetType pkt;
pkt.nTotalLength = 1;
pkt.nHeaderLength = 2;
...

send( s, (const char *) & pkt, sizeof pkt, 0 );

연산자 overloading 을 사용하면 메모리상에서는 network byteorder로
표현할때는 host 의 byte order로 변환되어 처리되니까
읽는 쪽도 아무 문제 없이 바로 읽을 수 있습니다.

도움이 됐을까요?

댓글 달기

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