网络编程中,关于socket传输中的大小端问题
在unix网络编成这本书中,提到过如果两台主机一个是大端一个是小端, 那么比如一端传输了一个short 的 0x0806那么对端就会收到 0x0608。(具体unix网络编成这本书是什么例子记得不大清楚了)先来说说我的认识:
在servaddr_in这个数据结构中,要给sin_port这个成员赋值就需要调用htons这个函数,来讲主机字节序装换位网络字节序,这就说明了一个问题,至少TCP或者UDP甚至SCTP协议或者说所有的四层协议(7层架构中),都不会去辨别主机是采用的什么字节序。这里我和同学有过一个讨论:
首先在网络中传输是用的大端字节序,然后我们讨论结果是不会产生大小端问题,为什么呢?我们是基于这样的假设,当发送内存数据实,会自动判断主机 字节序,然后转换为网络字节序发送出去,当接收方收到信息后判断自己的主机字节序,然后将网络字节序转为主机字节序,这样想好像是有道理的。因为网络字节序是标准的,只有一种字节序。
但是先前我们说了要调用htons来转后端口号这个参数,所以协议是没有帮我们自动识别大小端问题的。所以肯定会出错的,而我们的讨论是基于协议会自动帮我们识别主机字节序然后座相应转换,的却,我也认为这样做是很有道理的,但是不知道现在的协议为什么没有这样做。
例子1大小端传输:
如小端机器发送short的0x0806,即高地址存放0x08,低地址存放0x06----------发送的时候从低地址开始读取,即发送出去是0x0806--------大端主机依次读取从低地址开始存放数据,就是低地址存放0x06,高地址存放0x08,但是这个大端字节序,主机会把它解释为0x0608.
例子2大端到大端传输:
如大端端机器发送short的0x0806,即高地址存放0x06,低地址存放0x08----------发送的时候从低地址开始读取,即发送出去是0x0608--------大端主机依次读取从低地址开始存放数据,就是低地址存放0x08,高地址存放0x06,主机会把它解释为0x0806.结果正确
例子3小端到小端传输:
如小端机器发送short的0x0806,即高地址存放0x08,低地址存放0x06----------发送的时候从低地址开始读取,即发送出去是0x0806--------小端主机依次读取从低地址开始存放数据,就是低地址存放0x06,高地址存放0x08,主机会把它解释为0x0806.结果正确
说明:我也不知道写数据到socket是否是从低地址写道高地址,我也使根据函数的参数猜测的,如write函数会已一个起始地址为参数然后加上一个长度参数,从参数来判断应该是从低地址到高地址写数据。
从这三个例子中可以看到一些信息。但是如果我的假设是对的(不管从高地址还是低地址开始向socket写数据还是接收的时候得行为,只要是一致的算对),那这里就有一个问题:在网络传输中好像没有体现出网络字节序的问题,还是说因为这个模式其实网络字节序对我们来说是透明的。
unix网络编程也说过发送字符数据就不会产生大小端问题,但是如果是java这样的语言怎么办,他的字符时两个字节的这不是也会产生大小端问题吗,还是java在向socket(网络)写数据的时候会调用类似htons的函数来转换每个字符数据,但是这样工作量是不是太大了。那java是怎么做的呢?
望大家来解答下我的疑问,或者帮我思考思考,我想这个问题很久了,也没有大端的机器来做做试验。。。。。。