|
在学习unix网络编程的时候,遇到一个问题,那就是二进制数据在网络中传输中会受到大小端、机器位数等影响。那么如何影响呢?我手头有两台设备64位的ubuntu(小端)和32位linux开发板(MIPS架构、大端),说做就做。 我在32位机器(大端)上搭建服务端、在64位机器(小端)上搭建客户端。程序设计为客户端向服务端发送两个long类型的数据,服务端接收后将两个数据相加并返回给客户端。
服务端端核心代码如下:
for ( ; ; )
{
if ( (n = read(sockfd, &args, sizeof(args))) == 0)
return;
result.sum = args.arg1 + args.arg2;
printf("%ld-%ld\n", args.arg1, args.arg2);
write(sockfd, &result, sizeof(result));
} 客户端核心代码如下:
while (fgets(sendline, MAXLINE, fp) != NULL)
{
if (sscanf(sendline, "%ld%ld", &args.arg1, &args.arg2) != 2)
{
printf("invalid input: %s\n", sendline);
continue;
}
write(sockfd, &args, sizeof(args));
if (read(sockfd, &result, sizeof(result)) == 0)
{
printf("\033[32mread failed!\033[0m");
}
printf("%ld\n", result.sum);
}
测试数据为1 2 出乎意料的事情发生了,在得到两个意想不到的数后得到8589934593常数。 我把这个常数转换为16进制再去观察0x200000001,感觉到问题的关键了 64位系统小端发送1经过网络字节转换为01 00 00 00 00 00 00 00在32位机器上得到的arg1却是0x01 00 00 00,arg2为0x02 00 00 00,相加之和为0x01 00 00 00,然后发送给服务端,然后2继续转换:arg为0x02 00 00 00 ,arg2为0x 00 00 00相加后为0x02 00 00 00.客户端接收long类型是8个字节,等待服务端发生数据,然后只接收到4个字节的数据,这时会得到一个随机数,这里是140638704107521。这是第一次数据传输后的影响。 第二次,前面不变,客户端继续接收long,这时,在sock缓冲区,上一次剩余的结果(02 00 00 00)将被返回,所以这次也是一个随机数。这里是
140638704107522。 第三次,前面不变,客户端继续接收long,这时候,在sock缓冲区是这样的数据(01 00 00 00 02 00 00 00这时,小端接收会是20 00 00 00 1(第一个为符号位),原来是这样。 为什么第一次和第二次是随机数?原来这是在申请空间时没有初始化,将result结构体bzero就可以观察到,第一次接收1,第二次接收2. 源代码链接在这endian_test |