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) |