`
totoxian
  • 浏览: 1073894 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

通讯中的字节网络顺序和字节主机顺序

阅读更多
C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。
其实数据的顺序是由cpu决定的,与操作系统无关。
Intel x86结构下,short型数0x1234表示为34 12,int型数0x12345678表示为78 56 34 12
IBM power PC结构下,short型数0x1234表示为12 34,int型数0x12345678表示为12 34 56 78
由于这个原因不同的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序
PC开发中有ntohlhtonl函数可以用来进行网络字节和主机字节的转换,但是Symbian开发中没有这两个函数,那就要自己写接口来进行转换了。
下面是两个进行转换的接口:
//主机顺序转换成网络顺序网络顺序转换成主机顺序
inline unsigned long HTONL(unsigned long h)
{
return (h>>24)+((h>>16)<<8)+((h>>8)<<16)+(h<<24);
}
//主机顺序转换成网络顺序网络顺序转换成主机顺序
inline unsigned short HTONS(unsigned short h)
{
return (h>>8)+(h<<8);
}
这些问题在Java做为Server端,Symbian做为Client端时表现的更为明显,因为Java中的通讯传输的都是网络字节。到了Symbian端要转换成主机字节。
比如你要发送一个结构
structtest{
shorta;
int b;
longc;
floatd;
double f;
};
testst;
char*p = (char*)&st;//
看看p中的字节顺序(就是发送的字节顺序)

java
端你相应写些函数进行转换就行了。
举一个例子:
//
c对应的ntohl函数
public static long ntohl(long in){
long out = 0;
out = (in&0xff)<<24;
out |= (in&0xff00)<<8;
out |= (in&0xff0000)>>8;
out |= (in&0xff000000)>>24;
return out;
}
下面再转几篇不错的文章:
原文地址:http://blog.csdn.net/kingfish/archive/2005/03/29/333635.aspx

近几天看到csdn上问c/c++和java通信的问题比较多,特别是c特有的数据结构(如struct)。

特地根据网友的一个问题举个例子,希望对初学者有所帮助。

原问题见:http://community.csdn.net/Expert/topic/3886/3886989.xml?temp=.3527033

这类问题通常是为了利用原有Server或者Server不能做修改(通常是c/c++)造成。

比如Server端只接收一个结构Employee,定义如下:

struct UserInfo {
char UserName[20];
int UserId;
};
struct Employee {
UserInfo user;
float salary;
};
当然也可以定义为

struct Employee {
char name[20];
int id;
float salary;
};

java client 测试源码(为说明问题,假设struct字节对齐,sizeof(Employee)=28)

import java.net.*;

/*
* 与C语言通信(java做Client,c/c++做Server,传送一个结构)
* @author kingfish
* @version 1.0
*/
class Employee {
private byte[] buf = new byte[28]; //为说明问题,定死大小,事件中可以灵活处理

/*
* 将int转为低字节在前,高字节在后的byte数组
*/
private static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}

/*
* 将float转为低字节在前,高字节在后的byte数组
*/
private static byte[] toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}

/*
* 构造并转换
*/
public Employee(String name, int id, float salary) {
byte[] temp = name.getBytes();
System.arraycopy(temp, 0, buf, 0, temp.length);

temp = toLH(id);
System.arraycopy(temp, 0, buf, 20, temp.length);

temp = toLH(salary);
System.arraycopy(temp, 0, buf, 24, temp.length);
}

/**
* 返回要发送的数组
*/
public byte[] getBuf() {
return buf;
}

/**
* 发送测试
*/
public static void main(String[] args) {
try {
Socket sock = new Socket("127.0.0.1", 8888);
sock.getOutputStream().write(new Employee("kingfish", 123456789, 8888.99f).
getBuf());
sock.close();
}
catch (Exception e) {
e.printStackTrace();
}

} //end

当然,也可以利用writeInt,writeFloat方法发送,但字节顺序需要改为低在前。
这个问题稍后在讨论。

第一部分请见http://blog.csdn.net/kingfish/archive/2005/03/29/333635.aspx

本部分提出另外一种做法, 供参考。


import java.net.*;
import java.io.*;

/**
* 与C语言通信(java做Client,c/c++做Server,传送一个结构)
* @author kingfish
* @version 1.0
*/
public class Employee2 {
private String name;
private int id;
private float salary;

/**
* 将int转为低字节在前,高字节在后的int
*/
private static int toLH(int in) {
int out = 0;
out = (in & 0xff) << 24;
out |= (in & 0xff00) << 8;
out |= (in & 0xff0000) >> 8;
out |= (in & 0xff000000) >> 24;
return out;
}

/**
* 将float转为低字节在前,高字节在后的int
*/
private static int toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}

/**
* 构造并转换
*/
public Employee2(String name, int id, float salary) {
this.name = name;
this.id = id;
this.salary = salary;
}

/**
* 取得名字,定长byte数组
*/
public byte[] getName() {
byte[] b = new byte[20];
System.arraycopy(name.getBytes(), 0, b, 0, name.getBytes().length);
return b;
}

/**
* 取得编号(低字节在前)
*/
public int getId() {
return toLH(id);
}

/**
* 取得工资(低字节在前)
*/
public int getSalary() {
return toLH(salary);
}

/**
* 发送测试
*/
public static void main(String[] args) {
try {
Employee2 p = new Employee2("kingfish", 123456789, 8888.99f);

Socket sock = new Socket("127.0.0.1", 8888);
DataOutputStream dos = new DataOutputStream(sock.getOutputStream());
dos.write(p.getName());
dos.writeInt(p.getId());
dos.writeInt(p.getSalary());
sock.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
} //end

分享到:
评论

相关推荐

    网络字节顺序和主机字节顺序的转换

    ### 网络字节顺序和主机字节顺序的转换 在计算机网络中,不同硬件架构的设备之间进行数据通信时,必须确保数据的一致性和正确性。这其中包括了网络字节顺序(Network Byte Order)与主机字节顺序(Host Byte Order...

    网络字节序和主机字节序

    在网络编程中,为了保证数据在不同主机之间传输时能够被正确解释,需要使用统一的字节序,称为网络字节顺序。网络字节顺序采用 Big Endian 排序方式。 为了进行字节序转换,bsd socket 提供了四个函数:htons、...

    浅学字节序——字节序大小端,主机字节序,网络字节序的理解

    字节序,又称为字节顺序或字节排列方式,指的是在计算机内存中或网络传输过程中多字节数据的存储顺序。简单来说,它定义了多字节数据中各个字节如何按顺序排列。在实际编程工作中,尽管很多时候开发者可能不会直接...

    IEEE754浮点数与十六进制转换,带4字节的顺序调整

    在不同的字节顺序(Little-endian和Big-endian)系统中,这四个字节的顺序可能会有所不同。Little-endian系统中,最低有效字节(Least Significant Byte, LSB)位于最前面,而Big-endian系统中,最高有效字节(Most ...

    C++ 网络字节顺序转换函数、ip格式转换函数

    在C++编程中,网络字节顺序转换和IP地址格式转换是网络编程中常见的操作。网络字节顺序,也称为大端字节序,是一种在多处理器系统或网络通信中用于标准化数据表示的方式。IP地址则通常以字符串形式表示,但有时需要...

    c++和python如何实现主机字节序和网络字节序的相互转换

    在上一篇文章网络编程:主机字节序和网络字节序中,介绍了主机字节序和网络字节序的基本概念以及在实际的编程中,何时需要进行网络字节序和主机字节序的转换。本篇文章着重介绍使用c++和python语言,如何实现主机...

    字节存储顺序: little-endian小端,big-endian大端 教程

    你是否遇到过,内存中的数据顺序颠倒 你存入1234,实际存储的是3412. 字节存储顺序: little-endian小端,big-endian大端 教程 主机序,网络序 hton,ntoh

    kepware关联变量高低顺序问题

    当在KEPWARE中配置与S7-200 PLC的连接时,布尔型变量的表示方式有所不同,这可能会导致高低字节顺序的问题。 - **16位表示法**:在KEPWARE中,布尔型变量默认采用16位表示法,这意味着每个布尔型变量都映射到一个16...

    5_网络字节序_werevj4_

    在跨平台的网络编程中,字节序转换函数如htonl(主机到网络字节序,long)、ntohl(网络到主机字节序,long)、htons(主机到网络字节序,short)和ntohs(网络到主机字节序,short)非常常见,它们确保数据在网络上...

    络字节序、地址转换源代码

    在计算机网络中,数据传输涉及一个关键的概念:字节序,即字节在网络中的顺序。字节序分为两种类型:大端字节序(Big-Endian)和小端字节序(Little-Endian)。理解这两种字节序对于进行跨平台的网络通信至关重要,...

    ntohs, ntohl, htons,htonl的比较和详解.pdf

    在 C/C++ 中编写网络程序时,经常会遇到字节顺序的问题,即网络字节顺序(NBO)和主机字节顺序(HBO)的转换问题。这是因为计算机数据表示存在两种字节顺序:NBO 和 HBO。NBO 按从高到低的顺序存储,在网络上使用...

    大小端字节序介绍几转换

    在C++中,可以使用以下四个函数来完成主机字节序与网络字节序之间的转换: - `htons(unsigned short hostShort)`:将主机字节序的16位整数转换为网络字节序。 - `htonl(unsigned long hostLong)`:将主机字节序的32...

    Socket开发资料

    主机字节序和网络字节序 主机字节序即内存中存储字节的方法有: 1. Little endian:将低序字节存储在起始地址 2. Big endian:将高序字节存储在起始地址 网络字序表示网络协议在处理多字节时的顺序,一律为big ...

    网络字节序_werevj4_源码.rar

    网络字节序是计算机网络通信中的一个重要概念,它涉及到数据在网络中的传输方式。...通过学习和分析这些源码,开发者可以更好地理解字节序的概念,并能在自己的项目中正确处理网络数据的字节序问题。

    计算机网络习题一

    根据给定文件中的题目及其解析,我们可以总结出以下关键知识点,这些知识点涵盖了...以上内容是对给定文件中的习题及其解析所涉及的关键知识点的总结和扩展,希望能帮助读者更好地理解和掌握计算机网络的基础知识。

    IP分片时为啥片中数据长度要求为8字节的整数倍

    综上所述,IP分片中数据长度要求为8字节的整数倍是出于对IP头部中片段偏移字段的设计考虑,这一设计优化了网络传输效率和头部校验和的计算。在实际应用中,网络管理员和工程师应当理解这一点,合理配置网络设备的MTU...

    SOCKET网络编程基本知识整理

    - `htons()`:将主机字节顺序的无符号短整型转换为网络字节顺序。 - `htonl()`:将主机字节顺序的无符号长整型转换为网络字节顺序。 - `ntohs()`:将网络字节顺序的无符号短整型转换为主机字节顺序。 - `ntohl()...

    TCP网络通讯调试工具

    在IT行业中,TCP(Transmission Control Protocol)是一种广泛使用的网络通信协议,它为应用...了解并熟练运用上述TCP网络通讯调试工具和原理,可以帮助开发者有效地定位和解决网络通信问题,提高应用的稳定性和性能。

    Host-byte-order-to-network-.rar_byte order_doc

    在计算机网络中,数据传输涉及不同的系统和设备,它们可能使用不同的字节顺序来表示整数和浮点数。字节顺序是处理器架构中的一个重要概念,它定义了多字节数据类型(如整数和浮点数)在内存中如何存储字节。有两种...

    字节转换

    2. **字节序**:字节顺序分为大端字节序(Big-Endian)和小端字节序(Little-Endian),主要影响多字节数据如整数或浮点数的存储方式。大端字节序中,最高有效位(MSB)位于字节的低地址,而小端字节序则相反。跨...

Global site tag (gtag.js) - Google Analytics