大隐于市

用艺术的眼光看待编程!

用户操作
[即时聊天] [发私信] [加为好友]
孙东风ID:dongfengsun
137667次访问,排名592好友5人,关注者42
03年从西安交通大学毕业后一直从事移动平台的开发工作。崇尚一切自由的东西,热爱交流。目前专注于手机二维码技术研究并负责技术管理工作,希望能和同行认识、交流、共享。
dongfengsun的文章
原创 74 篇
翻译 2 篇
转载 33 篇
评论 164 篇
孙东风的公告
原创文章转载请注明出处
QQ :372590353
MSN:sundongfeng1227@hotmail.com
  我的EMAIL



最近评论
next163:上网的费用还是高了点我觉得。移动卡在那,真是一夫当关万夫莫开
xyz90830:可要知道手机平台太繁多了~要做普遍得很大财力 物力
xyz90830:可要知道手机平台太繁多了~要做普遍得很大财力 物力
thesameway:51旧书网 同城易书
www.51jiushu.com
www.51jiushu.net
二手书、旧书同城交易平台
分类齐全、快速发布、准确搜索
Microsoft_China_Vip:


www.soAsp.net 编程学习网 技术+ 实例应用 讲解不错。 推荐大家!

有很多 技术资料也很好!



文章分类
收藏
    相册
    存档
    订阅我的博客
    XML聚合  FeedSky

    原创 通讯中的字节网络顺序和字节主机顺序收藏

    新一篇: c/c++中指针参数如何传递内存 | 旧一篇: symbian数据类型转换

    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端要转换成主机字节。
    比如你要发送一个结构  
      struct test{  
        short   a;  
        int      b;
        long   c;  
        float   d;   
        double  f;  
      };  
      test st;  
      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

    发表于 @ 2007年01月30日 10:28:00|评论(loading...)|编辑

    新一篇: c/c++中指针参数如何传递内存 | 旧一篇: symbian数据类型转换

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 孙东风