0x0002 | 0x0003 | 0x0004 | ... |
|
|
빅 엔디안 모드와 스몰 엔디안 모드일 때 내용은 다음과 같이 저장됩니다
(1) 빅 엔디안 모드 저장(저장 주소는 16비트)
주소 데이터
0x0004(상위 주소) 0x44
0x0003 0x33
0x0002 0x22
0x0001(하위 주소) 0x11
(2) 리틀 엔디안 모드 저장(저장 주소는 16비트)
주소 데이터
0x0004(상위 주소) 0x11
0x00 03 0x22
0x0002 0x33
0x0001( 하위 주소) 0x44
2. 빅엔디안과 리틀엔디안
앞서 빅엔디안과 빅엔디안의 정의를 간략하게 설명하였고, 다음으로 간단한 예를 들어 설명하겠습니다. 설명:
1. 빅엔디안: 또는 빅엔디안 순서
A 유형: int32 숫자 0X0A0B0C0D의 메모리 저장 상황
데이터는 8비트입니다.
예제에서 , 가장 높은 유효한 비트는 가장 낮은 메모리 주소에 0x0A를 저장하고 그 다음 주소에 0x0B를 저장하는 것입니다. 이는 16진수 바이트의 왼쪽에서 오른쪽 순서와 유사합니다.
데이터는 16비트입니다
최상위 16비트 단위인 0x0A0B가 하위비트에 저장됩니다
2 리틀엔디안: 또는 리틀엔디안
데이터는 8비트입니다
예제에서 최하위 비트는 0x0D에 저장된 메모리 주소이며, 다음 주소에 순차적으로 저장됩니다.
데이터는 16비트 단위입니다
최하위 16비트 단위인 0x0C0D가 하위 비트에 저장됩니다.
3. 요약
빅엔디안 순서를 사용하는 CPU와 리틀엔디안 순서를 사용하는 CPU는 바이트 단위뿐만 아니라 비트 단위에서도 반대입니다.
예를 들어 메모리에 0x01을 저장하는 경우
빅 엔디안: 메모리 하위 비트 00000001 메모리 상위 비트
리틀 엔디안: 메모리 하위 비트 10000000 메모리 상위 비트
예: 0x00000001
빅 엔디안: 메모리 하위 비트 0000000 0 00000000 00000000 00000001 높은 메모리
리틀 엔디안: 낮은 메모리 10000000 00000000 00000000 00000000 높은 메모리
Application
사실 위에 나열된 것들은 결국 다음 단계를 위한 선택에 관한 것입니다. 언제 golang의 네트워크 전송 및 파일 저장에 관한 것입니다. 일반적으로 네트워크 전송의 바이트 순서는 소프트웨어가 시작될 때 통신 당사자의 프로토콜 규정에 따라 빅 엔디안 또는 리틀 엔디안이 될 수 있습니다. TCP/IP 프로토콜 RFC1700은 네트워크 바이트 순서로 "빅 엔디안" 바이트 순서의 사용을 규정하고 있으며 개발 중에 이 규칙을 따라야 합니다. 기본적으로 golang은 빅 엔디안 순서를 사용합니다. 자세한 내용은 빅 및 리틀 엔디안 순서 사용을 제공하는 golang의 인코딩/바이너리 패키지를 참조하세요.
import (
"encoding/binary"
"fmt"
)
func BigEndian() { // 大端序
// 二进制形式:0000 0000 0000 0000 0001 0002 0003 0004
var testInt int32 = 0x01020304 // 十六进制表示
fmt.Printf("%d use big endian: \n", testInt)
var testBytes []byte = make([]byte, 4)
binary.BigEndian.PutUint32(testBytes, uint32(testInt)) //大端序模式
fmt.Println("int32 to bytes:", testBytes)
convInt := binary.BigEndian.Uint32(testBytes) //大端序模式的字节转为int32
fmt.Printf("bytes to int32: %d\n\n", convInt)
}
func LittleEndian() { // 小端序
//二进制形式: 0000 0000 0000 0000 0001 0002 0003 0004
var testInt int32 = 0x01020304 // 16进制
fmt.Printf("%d use little endian: \n", testInt)
var testBytes []byte = make([]byte, 4)
binary.LittleEndian.PutUint32(testBytes, uint32(testInt)) //小端序模式
fmt.Println("int32 to bytes:", testBytes)
convInt := binary.LittleEndian.Uint32(testBytes) //小端序模式的字节转换
fmt.Printf("bytes to int32: %d\n\n", convInt)
}
func main() {
BigEndian()
LittleEndian()
}
출력 결과:
16909060 use big endian:
int32 to bytes: [1 2 3 4] ### [0001 0002 0003 0004]
bytes to int32: 16909060
16909060 use little endian:
int32 to bytes: [4 3 2 1] ### [0004 0003 0002 0001]
bytes to int32: 16909060
RPCX
RPCX 프레임워크에서 메시지 전달은 RPC 호출 프로세스는 빅 엔디안 모드
func (m Message) Encode() []byte { // 编码消息
// 编码metadata将key-value转为key=value&key=value形式
meta := encodeMetadata(m.Metadata)
spL := len(m.ServicePath) // 服务长度
smL := len(m.ServiceMethod) // 服务函数
var err error
payload := m.Payload // 消息体
if m.CompressType() != None { // 压缩
compressor := Compressors[m.CompressType()]
if compressor == nil { // 默认使用None压缩类型
m.SetCompressType(None)
} else {
payload, err = compressor.Zip(m.Payload) // GZIP压缩
if err != nil { // 压缩失败 不对传输消息进行压缩
m.SetCompressType(None)
payload = m.Payload }
}
}
// RPCX数据包 = header + ID + total size +
// 服务名及内容: servicePath(size(servicePath) 、len(servicePath)) +
// 服务函数及内容:serviceMethod(size(serviceMethod) 、 len(serviceMethod)) +
// 元数据及内容: metadata(size(metadata) 、len(metadata)) +
// 消息体及内容:payload(size(payload) 、 len(payload))
// 消息长度 = size(servicePath) + len(servicePath) + size(serviceMethod)
// + len(serviceMethod) + size(metadata) + len(metadata)
// + size(payload) + len(payload)
totalL := (4 + spL) + (4 + smL) + (4 + len(meta)) + (4 + len(payload))
// header + dataLen + spLen + sp + smLen + sm
// + metaL + meta + payloadLen + payload
metaStart := 12 + 4 + (4 + spL) + (4 + smL) // meata开始位置
payLoadStart := metaStart + (4 + len(meta)) // payLoad开始位置
l := 12 + 4 + totalL
data := make([]byte, l)
copy(data, m.Header[:]) // 拷贝header内容
// 将数据包以大端序模式进行编码
//totalLen
binary.BigEndian.PutUint32(data[12:16], uint32(totalL)) //
binary.BigEndian.PutUint32(data[16:20], uint32(spL))
copy(data[20:20+spL], util.StringToSliceByte(m.ServicePath))
binary.BigEndian.PutUint32(data[20+spL:24+spL], uint32(smL))
copy(data[24+spL:metaStart], util.StringToSliceByte(m.ServiceMethod))
binary.BigEndian.PutUint32(data[metaStart:metaStart+4], uint32(len(meta)))
copy(data[metaStart+4:], meta)
binary.BigEndian.PutUint32(data[payLoadStart:payLoadStart+4],
uint32(len(payload)))
copy(data[payLoadStart+4:], payload)
return data}
를 사용하여 인코딩됩니다. 【관련 추천: Go 비디오 튜토리얼, 프로그래밍 교육】