Chinaunix首页 | 论坛 | 博客
  • 博客访问: 438624
  • 博文数量: 132
  • 博客积分: 2511
  • 博客等级: 大尉
  • 技术积分: 1385
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-11 15:10
文章分类

全部博文(132)

文章存档

2012年(18)

2011年(35)

2010年(60)

2009年(19)

分类: LINUX

2010-10-24 22:42:06

uint16_t port;
port = htons(53);

在小端机上,53即0x0035
内存中的布局:
0x0000:0x35
0x0001:0x00

port = htons(53) = htons(0x0035) = 0x3500
内存中的布局:
0x0000:0x00
0x0001:0x35

--------------
看一个在小端机的本地进行转换的例子。
对53这个值来讲,其十六进制是0x0035,这都是字面值,在内存中,它的布局如下:
内存:
0x0000:0x35
0x0001:0x00
从字节流的角度来看,即...3500....
想把port转换成网络字节序,则port_net = htons(port) = htons(0x0035) = 0x3500,则port_net的内存布局:
0x0000:0x00
0x0001:0x35
从字节流的角度来看,即...0035....

当想把port_net再转换成主机字节序时,port_host = hons(port_net) = htons(0x3500) = 0x0035 = 53。
即hotns和ntohs的参数都是字面值,不是内存中的数据,相当于先把内存中的数据做一次解读,解读成相应主机字节序的值,再传给对应的函数,这样的操作才是对的。


-------------
看一个收包发的过程。
发包端,port=htons(53)=htons(0x0035),相当于port = 0x3500,则对port来讲,在小端机上,内存中的布局如下:
*(char *)&port:0x00
*((char *)&port + 1):0x35
则在发送端,buffer中就会按0035这样的顺序发送出去,在接收端,收到的内容在内存中应该也是0x0035
这样的形式。


在收包端,则收到的buffer中的内容是0x0035,解包时,uint8_t *p = buffer;
到port时,port = ntohs(*(uint16_t *)p)是正确的处理方式,那用*(uint16_t *)p读出来的是什么呢?
如果是0x0035,则相当于port = ntohs(0x0035),即port = 0x3500,显然这样是不对的。
*(uint16_t *)p如果读出来的是0x3500,则port = ntohs(0x0035) = 0x0035,port的字面值是对的。
因此,用*(uint16_t *)p得到的值,是将内存中的数据做过一次转换的值,已经被解读成了主机字节序。
此时可以看作这样的过程:
uint16_t tmp = *(uint16_t *)p;//tmp此时的字面值是0x3500
port = ntohs(tmp); //即port = ntohs(0x3500);
阅读(1414) | 评论(1) | 转发(0) |
0

上一篇:edns报文格式

下一篇:网易的公开课

给主人留下些什么吧!~~

chinaunix网友2010-10-25 16:24:17

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com