네트워크에서 구조체 자체를 넘기는 방법이 무엇입니까?
글쓴이: 불량도ㅐㅈㅣ / 작성시간: 화, 2005/11/15 - 11:12오후
struct PROTOCOL {
char id[8];
unsigned short len;
char cmd[4];
char dest[8];
char msg[490];
};
struct PROTOCOL protocol;
이러한 구조체에 각각 data를 입력한 후에,
다른 호스트에 이 구조체 자체를 넘겨서 그 쪽 호스트에서 이 구조체를 분석을 해야 합니다.
하지만 어떻게 구조체 정보를 통채로 넘길 수 있죠?
또, 받은 구조체 정보를 어떻게 분석을 해야 됩니까? memcpy()를 쓰면 되나요?
Forums:
struct PROTOCOL* pc;recv(sock, buf,
struct PROTOCOL* pc;
recv(sock, buf, sizeof(buf), 0);
pc = (struct PROTOCOL*)buf;
printf("id = %s\n", pc-> id);
단순하게 하면 이렇게 할수 있습니다.
실제 사용할려면... stream인걸 고려해서 추가적인 루틴이 필요합니다.
보낼때는struct PROTOCOL protocol; send(s
보낼때는
struct PROTOCOL protocol;
send(sock, &protocol, sizeof(struct PROTOCOL), 0);
아하 그렇군요~~ 감이 옵니다...^^
아하 그렇군요~~ 감이 옵니다...^^
문근영 너무 귀여워~~
두 머쉰이 바이트 오더가 다를 수 있고,구조체 정렬도 다를 수 있다는
두 머쉰이 바이트 오더가 다를 수 있고,
구조체 정렬도 다를 수 있다는 것을 고려한다면
네트워크에 자료를 보낼때나, 파일에 저장할 때
구조체를 통째로 보내거나 쓰면 안됩니다.
Orion Project : http://orionids.org
[quote="체스맨"]두 머쉰이 바이트 오더가 다를 수 있고,구조체
그러한 점이 있었군요~
뭐~ 실제로 쓸 거도 아니고, 과제로 나온 것이기 때문에
테스트로 해봤자 로컬머신에서 시작해서 로컬머신으로 끝나기 때문에 큰 문제는 없습니다. ^^
문근영 너무 귀여워~~
두 머쉰이 바이트 오더가 다를 수 있고, 구조체 정렬도 다를 수 있다
두 머쉰이 바이트 오더가 다를 수 있고,
구조체 정렬도 다를 수 있다는 것을 고려한다면
네트워크에 자료를 보낼때나, 파일에 저장할 때
구조체를 통째로 보내거나 쓰면 안됩니다.
바이트오더나 정렬과은 구조체의 전송 방법과는 다른 내용이고
구조체 전송이전에 맞춰야할 규약이죠. 구조체를 통째로 보내는거랑은 이런문제와는 조금 다릅니다. 그리고 구조체를 안쓰고 통신하는건 스트링을 다루는데 빼고는 본적이 없는것같군요.
웬만한곳에는 구조체 다써요.
[quote="Anonymous"]바이트오더나 정렬과은 구조체의 전송
제가 그것이 전송 방법이라 말씀드린 건 아니고 주의점으로
말씀드린 겁니다.
그런데 구조체를 통째로 주고 받고 하는 경우가 일반적이라는 것은
금시초문이군요. 그렇다면, 받는 쪽에서 뭔가 데이터를 받았는데,
보낸쪽 바이트오더와 구조체 정렬이 어떻게 되어있는지
모르는 상태에서 구조체 멤버들의 값을 정확히 복구해내는
방법이 무엇인지 설명 부탁드립니다.
구조체를 통째로 주고 받는 건, 두 머쉰이 바이트오더와
구조체 정렬이 동일하다는 가정하에 가능한 일입니다.
특히 구조체 정렬은, 지금이야 거의 없어졌지만, 컴파일러마다
다른 경우도 있어서, 동일한 사양의 두 머쉰이라도
다른 컴파일러를 사용해 빌드되었다면 통신이 불가능해질 수도
있지요.
파일에 저장할 때도 마찬가지 입니다. 바이너리 파일이 여러
머쉰에서 널리쓰이길 원하는 코드에서는 구조체를 통째로
저장하는 경우를 찾을 수 없으실 겁니다.
Orion Project : http://orionids.org
그런 내용들은 모든 프로토콜에 명시되어 있습니다.htonl과같은 함수
그런 내용들은 모든 프로토콜에 명시되어 있습니다.
htonl과같은 함수들이 있는 이유고요.
[quote="Anonymous"]그런 내용들은 모든 프로토콜에 명시되어
그래서 말씀입니다. htonl 을 쓰는 상황에서 구조체를
통째로 보내는 게 일반적이라는 것은 말이 안되지 않습니까?
* 그런데 어떤 손님이 어떤 손님인지 잘 모르겠군요...
Orion Project : http://orionids.org
전부 제글입니다.통째로 보낸다는 의미에서 어긋난듯하군요.님
전부 제글입니다.
통째로 보낸다는 의미에서 어긋난듯하군요.
님께서는 통째로 보낸다는 이야기를 변환없이 보낸다라고 생각하고
전 하나하나의 멤버를 따로 보내지 않고 한번에 보낸다라고 생각하고
약간의 어긋남이 있었던듯 싶네요.
그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.
바이트 오더를 잘 맞췄다해도 구조체를 통째로 보내는 일에는여전히 구조
바이트 오더를 잘 맞췄다해도 구조체를 통째로 보내는 일에는
여전히 구조체 정렬 문제가 남아있게 됩니다.
잘 아시겠지만, 멤버 b 의 옵셋은 머쉰 또는 컴파일러(옵션)에 따라
다르다고 가정해야 합니다. 받는측에서 곧바로 struct _data*
로 캐스트해서 바이트 오더를 조절하는 것으로 끝날 문제는
아니라는 거죠...
물론 해당 프로그램이 특정 머쉰에서만 작동하고 동일한 컴파일러로
빌드되어 배포된 경우에는 이런 것을 따질 필요는 없겠지요.
Orion Project : http://orionids.org
보통 linux 에서 c 로 다음과 같이 선언해서 쓰면정렬 문제는
보통 linux 에서 c 로 다음과 같이 선언해서 쓰면
정렬 문제는 피할수 있을듯 한데요 ...
바이트 오더링 문제는 구조체를 통체로 보낼때는
상관 없지 않나 합니다.
바이트 오더 문제는 2바이트 이상의 값을 보낼때는 구조체든무엇이든 항
바이트 오더 문제는 2바이트 이상의 값을 보낼때는 구조체든
무엇이든 항상 문제가 됩니다. 그래서 htons, htonl 같은
함수가 제공되지요.
pack 이 정렬 문제를 피할 수 있는 방법 중 하나이지만,
구조체 pack 은 C 표준이 아니고, 특정 시스템에서는
성능을 저하시키는 요인 중 하나가 됩니다.
자료를 전송할 때만 사용되는 것이 아니라면 되도록 피하는 것이 좋죠.
Orion Project : http://orionids.org
[quote="체스맨"]바이트 오더 문제는 2바이트 이상의 값을 보낼때는
체스맨님은 어떤 방법을 쓰십니까?
저 같은 경우는 프로토콜에 바이트오더를 명시하고 거의 pack 해서 보냅니다.
부득이하게 packed 할 수 없는 상황에서는 구조체안에 padding bytes(이게 맞는 말인지는 모르겠습니다만-_-)를 포함시켜 선언한 후 전송하구요.
다른 좋은 방법이 있다면 저도 알고싶습니다.
얼레.. 왜 손님으로 글이 써졌지-_-;; 위에 글이 접니다.
얼레.. 왜 손님으로 글이 써졌지-_-;; 위에 글이 접니다.
dasomoli의 블로그(http://dasomoli.org)
dasomoli = DasomOLI = Dasom + DOLI = 다솜돌이
다솜 = 사랑하옴의 옛 고어.
Developer! ubuntu-ko! 다솜돌이 정석
일단 바이트 오더 문제가 고려된 뒤에는...저라고 뭐 뾰족한 좋은
일단 바이트 오더 문제가 고려된 뒤에는...
저라고 뭐 뾰족한 좋은 수가 있겠습니까? ^^
뾰족한 수가 있었으면 이미 첫 답글 쓸 때 같이 써놓았겠죠.
구조체 팩도 그게 지원되는 컴파일러면 하나의 방법이지만,
C 표준이 아니어서 저같은 경우는 잘 안씁니다.
그냥 1바이트 배열로 전송합니다.
대부분 네트워크 패킷 스팩을 봐도 바이트열로 정의되어 있구요...
보낼 값들을 1바이트 배열로 전환하는 것은 뭐, 효율적으로 잘 해야겠지요.
패딩된 바이트를 포함해서 보내는 것이 일반적인 방법일 수는 없습니다.
보내는쪽 구조체 정렬 방법을 모르면, 받는 쪽에서 값을 얻지 못할 수 있으니까요.
구조체 정렬도 표준에 정의된 바 없습니다.
Orion Project : http://orionids.org
당연히 오더링 맞춰서 보내야죠. 네트웍에선 주로 빅엔디안을 표준으로보
당연히 오더링 맞춰서 보내야죠. 네트웍에선 주로 빅엔디안을 표준으로
보고 있는 것으로 알고 있습니다. 헌데 intel칩의 경우엔 리틀엔디안이죠.
바이트 오더링 꼭 체크 해야 하는게 맞습니다.
아니면 아예 프로토콜에다가 항목을 정해 놓으시던가요.
스트럭쳐의 경우에 32비트 컴퓨터랑 64비트 컴퓨터랑 내용이 달라질 수도
있으니까 주의 하시고(확인은 안해 봤습니다) 스트럭쳐를 통채로 그냥 보내는
일은 가급적 피하시는게 좋을듯 합니다.
뭐, 간단한 프로토콜이거나 네트웍에 물린 컴퓨터나 프로그램이 동작하는
컴퓨터가 한정적이고 빤~하다면 상관은 없겠죠.
표준의 범위 내에서는 해결이 불가능한 문제입니다. 이것은 구조체의 값을
표준의 범위 내에서는 해결이 불가능한 문제입니다. 이것은 구조체의 값을 이진 파일로
쓴 다음 다른 환경에서 읽어들여 그 값을 복원하는 것과 본질적으로 같은 문제입니다.
아시다시피 이진 파일은 메모리의 비트열을 그대로 덤프하는 것이죠. 동일한 환경에서
읽고 쓴다면 전혀 손실없는 복원이 가능하지만, 다른 환경에서는 데이터의 이식성이
보장되지 않습니다.
- 서로 다른 플랫폼에서는 바이트 오더링과 정렬이 달라질 수 있다.
- 서로 다른 플랫폼에서 바이트 오더링과 정렬이 같다고 해도 예를 들어 정수 0을
표현하는 비트열이 달라질 수 있다.
- 바이트 오더링과 정렬에 관계없는 문자열도 서로 다른 플랫폼에서 다른 문자 세트를
사용한다면 어떤 특별한 매핑이 없이는 복원이 불가능하다.
- 동일한 플랫폼이라도 읽는 프로그램을 빌드할 때의 옵션(바이트 오더링, pack
외에도 다른 옵션이 관련될 수 있음)과 쓰는 프로그램을 빌드할 때의 옵션이 다르면
실제로 다른 플랫폼에서의 이진 파일을 문제없이 다루는 프로그램도 있던데 어떻게그 역시 보장할 수 없다.
하는지 정말 궁금합니다. 나중에는 저도 이거 해야 하는데... --;[/]
쉽게 TCP/IP 프로토콜 명세만 보셔도 binary format으로 어
쉽게 TCP/IP 프로토콜 명세만 보셔도 binary format으로 어떻게 맞출 수 있는지는 답이 나옵니다. 당연히 struct 로 주고 받으면 안됩니다. 해보니 프로토콜 명세와 맞더라.. 해도 하면 안됩니다.
char[] 로 보내고/받을 buffer를 잡으시고 안에 내용을 명세에 맞고 network order로 넣으시면 됩니다.
이 작업이 귀찮으시면 버퍼 관리, 데이터 타입에 따른 변환을 하는 라이브러리를 사용하시면 됩니다.
이런 작업이 귀찮으시면 그냥 XML로 주고 받으시면 됩니다. ;)
----------------------------------------
http://moim.at
http://mkhq.co.kr
[quote="irondog"]당연히 오더링 맞춰서 보내야죠. 네트웍에선
바이트 패딩이면 얘기가 다를수도 있겠지만...
바이트 오더의 문제는... 경우에 따라 상관없을수도 있지 않나요?
예를 들어... 이 어플리케이션은 x86플랫폼의 윈도우즈 에서만 사용된다 라는 게 정해지면
바이트오더 문제는 고민할 필요가 없다고 생각됩니다만...?
----------------------------------------------
한번뿐인 인생....
미친듯이 살아보자!
----------------------------------------------
흠.. 그래서 전 구조체에 함수를 만들어서 멤버별로 각각 전송하는 코드를
흠.. 그래서 전 구조체에 함수를 만들어서 멤버별로 각각 전송하는 코드를 사용하기도 합니다.
물론 저 혼자 쓸껀 그냥 통채로 보내구요..
일로 하는건 최대한 다양한 상황에 쓰일 수 있음을 고려를 하죠..
ㅡ_ㅡ;
char buf[4]; int32_t a;a를 buf로 옮기는거나 스
char buf[4]; int32_t a;
a를 buf로 옮기는거나 스트럭쳐에서 바이트 오더링을 하는거나 같지 않나요?
넓게보면 int도 구조체에 포함시킬수 있습니다. 이걸 피해갈려면 int형자체를 쓸 수 없게 됩니다.
남은건 정렬문제입니다.
그리고 범용적으로 사용할것이라면 아래와 같이 설계하지 않을듯 합니다.
typedef struct _test {
char a;
int32_t b;
} test_t;
typedef struct _test {
char a;
char preserved[3];
int32_t b;
} test_t;
사용하고 안 사용하고는 현재 개발의 환경, 목적에 따라 결정할 수 있는 문제이지 안된다고 못밖긴 힘듦니다.
스트럭쳐를 직접적으로 전송하는 방법이 상당히 좋치 못한 방법이라면
linux에서 지원되는 recv함수는 죄악입니다. 왜 char*형으로 지정하지않고 void*로 했을까요. :(
ip헤더를 읽을 려고 한다면 char buf로 받아서 일일이 변환해야 되겠지만...
형변환 할수 있도록 linux는 한번에 읽도록 제공합니다.
확실한건 아니지만 ㅡㅡ 거의 맞을겁니다. 가물가물
linux의 tcp스택 역시 스트럭쳐를 바이트 오더링한 다음, 헤더를 그대로 buff로 write하는 걸로 알고 있습니다.
일반화 시키긴 힘들겠지만 제가 본 몇가지 프로토콜을
구현한 소스들은 char buf로 재구성해서 보내는걸 본적이 없습니다.
멀티플렛폼이라면 XDR같은걸 쓰는게 원칙입니다만 정황으로 봐서 그런것까진
멀티플렛폼이라면 XDR같은걸 쓰는게 원칙입니다만 정황으로 봐서 그런것까진 필요 없을듯 싶군요..
[quote="alsong~"]char buf[4]; int32_t a;
같지요. 하지만 그것을 지적하진 않았습니다.
이 구조체는 이미 a 멤버 주소로부터 4바이트 옵셋 위치에 멤버 b
가 반드시 위치한다는 가정하에 가능한데요, 이미 말씀드렸듯이
그 가정이 틀릴 수도 있다는 겁니다. 게다가 이미 정해진 스펙이라면
pack 구조체가 아닌 이상 옵셋을 맞출 수가 없지요.
리눅스는 운영체제이고 빌드할 컴파일러나 작동할 하드웨어 시스템에
대한 스펙이 이미 결정되어있다는 가정하에 말씀하신 것처럼
reserved bytes 를 끼워 넣는 등으로 구현이 가능합니다.
운영체제라면 효율적인 방법을 택하는 게 가장 좋겠지요.
아무튼 스트럭쳐를 그대로 보내는 게 상당히 나쁜 방법이라고는
생각하지도 않고 그렇게 말씀드리지도 않았구요..
상위 응용 프로그램을 만드는 입장에서는 우선 기본적으로
구조체를 그대로 보낼때 주의해야 할 점이 있기 때문에
구조체를 그대로 보내는 것이 일반적인 방법이라 생각해서는
안된다는 것을 지적하고 싶었습니다. 그리고 검토하신 소스들은
저도 좀 볼 수 있게 구할 수 있는 곳을 알려주셨으면 합니다.
사실 회사 업무에서 소스들을 보면 구조체로 하는게 쉽기 때문에
pack 옵션을 써서 되어있습니다. 그런데 해당 구조체 뿐 아니라
전체 프로젝트에 모두 pack 옵션을 걸어버리는 폭력적인 접근법을
보면 좀 그렇더라구요...
Orion Project : http://orionids.org
검토하신 소스들은 저도 좀 볼 수 있게 구할 수 있는 곳을 알려주셨으
검토하신 소스들은
저도 좀 볼 수 있게 구할 수 있는 곳을 알려주셨으면 합니다.
오히려 char로 재배열한 소스를 보고 싶군요. 이런 요청은 먼저 제시후
샘플을 요청하시기 바랍니다.
리눅스의 ip, tcp스택을 보시고 sctp프로트콜을 보시기 바랍니다.
그리고 글전체적질문에대한 답이었습니다.
해당사항을 읽으볼때 사용할때 주의해야한다라는 내용보다
안좋다 쓰지마라는 내용으로 흘러가고 있어서 이야기하는겁니다.
혹시라도 오해가 없으셨으면 합니다. 검토하신 소스를 구할 수있는 곳을
혹시라도 오해가 없으셨으면 합니다. 검토하신 소스를 구할 수
있는 곳을 알려달라 말씀드린 건, 그런 소스가 어디있겠냐 같은
의도가 아니라 어떤 상황에서 그렇게 했는지 알고싶어서였습니다.
말씀드렸듯이, 리눅스 소스라면 운영체제이기 때문에그렇게 하는 게
더 옳다고 봅니다.
제가 말씀드릴 수 있는 소스는 ethereal 에서 dissectors
부분입니다. 패킷 분석할 때 기본적으로 바이트 스트림을
이용합니다. 그리고, 회사 업무가 통신쪽이라, 각종 스펙들을
접하는데 모두 바이트열로 정의되어 있습니다. 물론 스펙과 구현은
별개이지만요.
파일저장하는 것도 결국 마찬가지인데 오래되어서 어느
소스였는지 기억이 안나지만, 구조체 멤버를 하나씩 fwrite 호출하는
루틴이 있었습니다. 당시에는 바이트 오더나 구조체 패딩같은 개념이
없어서, 그냥 한방에 할 걸 왜 이렇게 했나 생각했었습니다.
아무튼 주의해야한다가 맞습니다. 만일 게임 서버 개발하는데
한정적인 운영체제만 사용되는 상황에서 바이트 오더 맞추고,
pack 할 필요는 없겠지요.
Orion Project : http://orionids.org
중요한것은 프로그래머가 제어할 수 있는가, 혹은 아닌가의 문제입니다. 그
중요한것은 프로그래머가 제어할 수 있는가, 혹은 아닌가의 문제입니다. 그냥 구조체 통째로 보내도 프로그래머가 어떤 내용이 어떤 순서로 가는지를 확신하고 제어할 수 있다면 그렇게 해도 됩니다. 하지만 자신이 없다면 안전장치를 갖추는 것이 좋을 겁니다.
근데 문제는, 그냥 보내기 위해서는 퍽이나 고려해야 될 사항이 많다는 것입니다. 시스템의 byte order, 구조체 안의 padding, 컴파일러 옵션 등등... 가장 골때리는 것은 역시 구조체 안의 padding 입니다. 크기도 지맘대로고 그 안의 내용도 지맘대로입니다.
이식성을 위해서라면, 구조체를 char형 배열로 pack 하는 별도의 처리과정을 집어넣는 것이 현명합니다. 지금 당장 그럴 필요가 없다면, 그냥 껍데기만이라도 만들어 두는것이 좋습니다. 그럼으로써 나중에 고쳐야 될 순간이 올때 훨씬 쉽게 작업할 수 있을 것입니다.
조금 주제에서 벗어나는 얘기가 될지도 모르겠지만저라면 네트웍 프레
조금 주제에서 벗어나는 얘기가 될지도 모르겠지만
저라면 네트웍 프레임 워크 사용을 고려할것 같습니다.
일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.
[quote="Anonymous"]멀티플렛폼이라면 XDR같은걸 쓰는게 원
good!
XMLRPC 또는 SOAP를 사용하는 것이 나을 것 같은데요.플랫폼에
XMLRPC 또는 SOAP를 사용하는 것이 나을 것 같은데요.
플랫폼에 따른 엔디안, 패딩 문제 고려할 필요 없고,
소켓 연결도 어느정도 추상화해주기 편리하구요.
[quote="scroller"]XMLRPC 또는 SOAP를 사용하는 것
대용량으로 가면 XML 파싱에 CPU 로드가 높아집니다.
----------------------------------------
http://moim.at
http://mkhq.co.kr
[quote="쌀밥"]조금 주제에서 벗어나는 얘기가 될지도 모르겠지만
어떤 네트웍 프레임워크가 좋을까요?
삽질의 대마왕...
ASN1 이나 XML Schema 가 좋을듯...
ASN1 이나 XML Schema 가 좋을듯...
[code:1]두 머쉰이 바이트 오더가 다를 수 있고, 구조체 정렬도
체스맨님 의견에 동의합니다..
구조체 덤프해서 보내는건 사파의 무공입니다~~
구조체 사용도 빈번하게 생깁니다.
바이너리를 다루는 형태는 종종 사용되기도 하기 때문에 구조체를 쓸때는 XDR을 주의해서 참고하시면 됩니다.
RFC-1832 번입니다. 한번은 꼭 읽어볼만한 RFC문서중 하나입니다.
참고로 텍스트로 통신을 하면 대개는 좋지만, 몇몇의 경우에는 데이터의 특성이나 확장에 있어서는 오히려 비효율적이기도 합니다.
[code:1]struct PROTOCOL { u
recv(sock, protocol.data, 512, 0)
대충 이런식으로 사용하면 안되나요???
흠.. 될것 같은데..
union으로 하는거나 구조체 주소를 char*형으로 형변환해서 넘기는거
union으로 하는거나 구조체 주소를 char*형으로 형변환해서 넘기는거나 똑같은 문제가 있습니다.
문제는 자료형의 byte order 문제와 구조체 안의 padding이죠.
댓글 달기