// 套接字通信分两部分:
- 服务器端:被动接受连接,一般不会主动发起连接
- 客户端:主动向服务器发起连接
socket是一套通信的接口,Linux 和 Windows 都有,但是有一些细微的差别。
上图0x11是最高位,所以放在高地址处(内存地址增长方向)。
上图0x12是最高位,所以放在低地址处。
判断本地主机是大端序还是小端序代码:
/*
字节序:字节在内存中存储的顺序。
小端字节序:数据的高位字节存储在内存的高位地址,低位字节存储在内存的低位地址
大端字节序:数据的低位字节存储在内存的高位地址,高位字节存储在内存的低位地址
*/
// 通过代码检测当前主机的字节序
#include <stdio.h>
int main() {
union {
short value; // 2字节
char bytes[sizeof(short)]; // char[2]
} test;
test.value = 0x0102;
if((test.bytes[0] == 1) && (test.bytes[1] == 2)) {
printf("大端字节序\n");
} else if((test.bytes[0] == 2) && (test.bytes[1] == 1)) {
printf("小端字节序\n");
} else {
printf("未知\n");
}
return 0;
}
h - host 主机,主机字节序
to - 转换成什么
n - network 网络字节序
s - short unsigned short
l - long unsigned int
#include <arpa/inet.h>
// 转换端口
uint16_t htons(uint16_t hostshort); // 主机字节序 - 网络字节序
uint16_t ntohs(uint16_t netshort); // 网络字节序 - 主机字节序
// 转IP
uint32_t htonl(uint32_t hostlong); // 主机字节序 - 网络字节序
uint32_t ntohl(uint32_t netlong); // 网络字节序 - 主机字节序
测试代码如下:
/*
网络通信时,需要将主机字节序转换成网络字节序(大端),
另外一段获取到数据以后根据情况将网络字节序转换成主机字节序。
// 转换端口
uint16_t htons(uint16_t hostshort); // 主机字节序 - 网络字节序
uint16_t ntohs(uint16_t netshort); // 网络字节序 - 主机字节序
// 转IP
uint32_t htonl(uint32_t hostlong); // 主机字节序 - 网络字节序
uint32_t ntohl(uint32_t netlong); // 网络字节序 - 主机字节序
*/
#include <stdio.h>
#include <arpa/inet.h>
int main() {
// htons 转换端口
unsigned short a = 0x0102;
printf("a : %x\n", a);
unsigned short b = htons(a);
printf("b : %x\n", b);
printf("=======================\n");
// htonl 转换IP
char buf[4] = {192, 168, 1, 100};
int num = *(int *)buf;// 强转成int *,是4个字节,buf一共4个字节
int sum = htonl(num);
unsigned char *p = (char *)∑
printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));
printf("=======================\n");
// ntohl
unsigned char buf1[4] = {1, 1, 168, 192};
int num1 = *(int *)buf1;
int sum1 = ntohl(num1);
unsigned char *p1 = (unsigned char *)&sum1;
printf("%d %d %d %d\n", *p1, *(p1+1), *(p1+2), *(p1+3));
// ntohs
return 0;
}
输出结果为:
再来看一下a和b的输出疑问:?
gpt的解答:
你的理解基本正确,我会进一步解释一下。
在计算机中,整数在内存中以二进制形式存储,而不同的字节序会影响在内存中的表示方式。对于小端序(Little Endian)机器,最低有效字节存储在最低内存地址,而对于大端序(Big Endian)机器,最高有效字节存储在最低内存地址。
当你使用 `%x` 格式化输出时,实际上是将内存中的二进制数据格式化为十六进制字符串,这并不会改变数据在内存中的存储方式。因此,`a` 在小端序机器上在内存中的表示是 `02 01`,但是在使用 `%x` 输出时,它被格式化为 `0x0102`,这只是一种表示形式。
同样,`htons` 和 `htonl` 等函数并不改变内存中的实际存储方式,它们只是负责在不同字节序之间进行转换。这些函数的目的是确保在网络通信中数据的一致性,而不是改变内存中的存储方式。
所以,你的理解是正确的:输出的值是通过格式化方式呈现的,而不是真正改变了内存中的存储方式。