2010-04-19 5 views
6

네트워크를 통해 데이터를 전송하는 데 QUdpSocket을 사용하는 프로그램을 작성하고 있습니다. 이것은 나의 첫번째 소켓 프로그램이고 Endianness라는 흥미로운 문제를 보았습니다.Qt 소켓 및 엔디안 방식

내 소켓 라이브러리로 QNetwork를 사용할 때 내 실제 질문에 엔디 언 어를 걱정해야합니까? 걱정할 필요가 없다면 엔딩 문제를 제대로 피하기 위해 무엇을해야합니까?

미리 감사드립니다.

답변

11

일반적으로 한 컴퓨터에서 다른 컴퓨터로 한 바이트보다 큰 정수를 전송할 때 엔디 언 (바이트 순서)에 대해 걱정할 필요가 있습니다. C/C++에서는 16 비트, 32 비트 또는 64 비트 정수를 보내는 경우 정수를 네트워크 바이트 순서 (Big-Endian이라고도 함)으로 변환해야합니다.). 수신 측의 컴퓨터는 들어오는 정수를 호스트 바이트 순서으로 변환해야합니다. 호스트 컴퓨터는 기본적으로 호스트 시스템이 사용하는 바이트 순서입니다. 이것은 대개 htonsntohs 라이브러리 함수 시리즈를 사용하지만 Qt 라이브러리를 사용하면 qToBigEndianqFromBigEndian 함수를 사용할 수도 있습니다.

ASCII 또는 UTF-8 텍스트를 보낼 때 엔디안을 걱정할 필요가 없습니다. 이러한 형식은 멀티 바이트 데이터 형식이 아닌 개별 바이트 시퀀스로 구성되기 때문입니다.

+0

스트리밍을하는 경우 언제든지이 작업을 수행 할 필요는 없습니다. o 모든 바이트를 hton으로 변환 한 다음 다시 다시 변환하는 것은 이해가되지 않습니다. 따라서 수신 시스템이 데이터의 어느 쪽이 길 었는지 알 수 있도록 코드를 만드는 것이 좋습니다. –

+0

잘못된 UTF-8은 가변 폭 인코딩으로 모든 유니 코드 문자를 나타낼 수 있으며 최대 4 바이트까지 사용할 수 있습니다. –

+0

아니요, 이해가 잘못되었습니다. UTF-8은 가변 폭 인코딩이지만 UTF-16 또는 UTF-32와 달리 가변 길이 문자가 정렬 된 바이트 시퀀스로 구성되어 있기 때문에 엔디안의 영향을받지 않습니다. 최소 단위는 2 (또는 4) 바이트의 2 진 정수입니다. 그의 바이트 순서는 아키텍처 엔디안에 의해 결정됩니다. –

2

다른 엔디안을 사용하는 두 시스템간에 바이너리 데이터를 전송하는 경우 걱정할 필요가 있습니다.

네트워크 소켓은 데이터를 변경하지 않고 출하합니다. 다른 컴퓨터에서 전송 된 바이트가 특정 순서로 있다고 가정하면이를 관리해야합니다.

이미지와 같이 알려진 형식으로 데이터를 전송하는 경우 일반적으로 이미지 형식은 머리글에 어떤 순서로 표시되는지 표시하기 위해 헤더에 내용이 있으며 판독기/기록기 라이브러리가이를 처리합니다. 자신 만의 바이너리 형식을 발명한다면, 그것은 당신에게 달려 있습니다. 크기를 고려해야 할 수도 있습니다. 다른 컴퓨터의 int는 몇 바이트입니까?

좋은 소식은 대부분의 기계가 Intel이며 대부분의 응용 프로그램에서 ASCII 형식으로 적은 양의 데이터를 출하 할 수 있다는 것입니다.

0

인텔 CPU는 리틀 엔디안을 사용합니다. 그 밖의 대부분은 빅 엔디안입니다. 기본 네트워크 바이트 순서는 빅 엔디안입니다.

엔디안이 문제가되는지 테스트하려면 0x12345678 값을 보내고 동일하게 또는 0x78563412로 설정하는지 확인하십시오. 수신 컴퓨터의 값이 나중 값이면 엔디안은 두 시스템간에 동일하지 않습니다.

엔디 언스에 대한 정보는 this wikipedia article을 확인하십시오.

//이 테스트는 적어도 2의 INT의 크기를 가정 : 당신이 그것을 원하는 경우에

+0

인텔 CPUS는 리틀 엔디안을 사용합니다. 이는 OS의 기능이 아닙니다. –

+3

Windows에서 리틀 엔디안을 사용한다고 말하면 오해의 소지가 있습니다. "기타 모든 제품"은 빅 엔디안을 사용합니다. 엔디안은 OS가 아닌 프로세서 아키텍처의 속성입니다. 대부분의 가정용 컴퓨터는 리틀 엔디안입니다. 인텔 및 AMD x86 프로세서는 리틀 엔디안이기 때문입니다. 여기에는 Windows 이외의 Linux 또는 다른 OS를 실행하는 x86 컴퓨터가 포함됩니다. –

+0

예 인텔 맥은 리틀 엔디안이고, PowerPC는 빅 엔디안 (칩은 전환 가능하지만 Mac은 기본 모드를 사용했습니다.), ARM (iStuff)은 구현이 정의되었습니다 –

1

여기에, 큰 엔디안에 대한 간단한 테스트입니다.

static const int testValue = 1;

#DEFINE의 is_bigendian() (((CHAR) & testValue) == 0)

부울 CD_is_bigendian (공극) { 복귀 is_bigendian(); }

+0

미래에이를 참조하는 사용자는 원하는 것으로 생각할 수 있지만 실제로 : https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html – josaphatv

1

나는 이것이 오래 전 대답했지만, 나는 그것에 덧붙였다 고 생각했다.

대신 엔디안 변환 기능을 사용하여, 당신은 쉽게 많이 내 의견에보다 직관적 이다, (어떤 QIODevice 사용) QDataStream 기능을 사용할 수 있습니다. 물론, 그것은 송신자와 수신자 모두에서 QDataStream을 사용하게 할 것이지만,이 경우에는 그만한 가치가 있습니다.

사용 예제, 이미지를 보내는 누군가 다른 사람의 샘플 :

QDataStream & operator<< (QDataStream& stream, const QImage& image);
QDataStream & operator>> (QDataStream& stream, QImage& image);
(그 중 둘은 이미 Qt를 내에서 구현됩니다.)

QTcpSocket *tcp = ...;
QImage img = ...;
QDataStream(tcp) << img;