Socket网络通讯开发总结之:Java 与 C进行Socket通讯

http://blog.sina.com.cn/s/blog_55934df80100i55l.html

(2010-04-08 17:26:29)

 

先交待一下业务应用背景: 服务端:移动交费系统:基于C语言的Unix系统 客户端:增值服务系统:基于Java的软件系统 通迅协议:采用TCP/IP协议,使用TCP以异步方式接入 数据传输:基于Socket流的方式,传输的是网络字节序
Java Socket通讯实现方式这里不做过多的描述,网上到处可以搜索到,比较简单,这里要说的是Java 与 C 进行Socket通讯需注意的地方:

1、Java与C的各种数据类型存储的字节数是不同的:

Java与C的数据类型的比较

Type      Java      C   
  short      2-Byte   2-Byte   
  int        4-Byte   4-Byte   
  long       8-Byte   4-Byte   
  float      4-Byte   4-Byte   
  double     8-Byte   8-Byte   
  boolean    1-bit     N/A   
  byte       1-Byte    N/A   
  char       2-Byte    1-Byte

所以在通讯前,需要进行类型转换,对于C定义的unsign char为一个字节存储,对应Java这边用byte存储;对于C定义的int, long, float对应Java用int存储,具体可以参考以上的表。

所以在通讯前,需要进行类型转换,对于C定义的unsign char为一个字节存储,对应Java这边用byte存储;对于C定义的int, long, float对应Java用int存储,具体可以参考以上的表。

2、Socket通讯是按字节传输的(即8个bit位传输),而对于超过一个字节的类型如short 为两个字节,

就存在两种传输入方式,一种是高字节在前传输;一种是高字节在后传输。即Little-Endian和Big-Endian。
Little-Endian和Big-Endian是表示计算机字节顺序的两种格式,所谓的字节顺序指的是长度跨越多个字节的数据的存放形式. 
        假设从地址0x00000000开始的一个字中保存有数据0x1234abcd,那么在两种不同的内存顺序的机器上从字节的角度去看的话分别表示为: 
       1)little endian:在内存中的存放顺序是0x00000000-0xcd,0x00000001-0xab,0x00000002-0x34,0x00000003-0x12 
       2)big  endian:在内存中的存放顺序是0x00000000-0x12,0x00000001-0x34,0x00000002-0xab,0x00000003-0xcd 
       需要特别说明的是,以上假设机器是每个内存单元以8位即一个字节为单位的. 
       简单的说,ittle endian把低字节存放在内存的低位;而big endian将低字节存放在内存的高位. 
       现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian.

网络协议都是Big-Endian的,Java编译的都是Big-Endian的,C编译的程序是与机器相关的,具体是否要进行转换是需要沟通的。假设这里需要转换,以下提供short转的换成字节数组的方式:

public static byte[] ShorttoByteArray(short n) {
    byte[] b = new byte[2];
    b[1] = (byte) (n & 0xff);
    b[0] = (byte) (n >> 8 & 0xff);
    return b;
  }

public static byte[] toLH(short n) {
    byte[] b = new byte[2];
    b[0] = (byte) (n & 0xff);
    b[1] = (byte) (n >> 8 & 0xff);
    return b;
  }
其它的类型转换类似,无非是根据类型在判断用几个字节进行存储而已。

3、由于Socket通讯是按字节进行传输的,而在Java中只有byte是一个字节,故可以将其它类型都转换成byte数组来存储,

如:short用两位的字节数组存储,需转换了换以上方法进行,而int用四位的字节数组来存储,对String类型,直接用String.getBytes()来得到它的字节数组。

4、Java的byte与C语言的unsign char虽然都是一个字节存储,但具体的表示内容是不同的,

C的无符号char是取值的范围0--255,而Java中byte取值的范围是-128—127,故在实现C语言的字符串时(C是用char[]来表示字符串的),

Java这边需要进行转换来模仿C语的unsign char,

具体实现函数如下:
  // 将有符号的char转换成无符号的char
  public static char[] ToUnsignedChar(char[] signChar) {
    for (int i = 0; i < signChar.length; i++) {
      int x = ((byte) signChar[i]) >= 0 ? signChar[i] : ((byte) signChar[i]) + 256;
      signChar[i] = (char) x;
    }
    return signChar;
  }
这里的关键点是当signChar[i] < 0时,即加上256,将其转换到0--255中来。
通过以上四个方面的注意,基本上就可以实现Java与C进行Socket通讯了

[备忘] Java和C之间的通讯

 http://www.smithfox.com/?e=119

Java和C之间完全可以用二进制报文通讯, 只要注意几点, 就不必担心 String, Int类的组装和解析问题.

1. 无论什么CPU, Java都会以标准的网络字节序传送数据, 所以C语言也要按网络字节序传送, 需要调用ntohx和htonx系列函数.

2. C语言没有定义int类型的大小, 考虑到现在很多的Server已经是64位, 所以需要用int16_t, int32_t, int64_t来代替shor, int和long long.

3. Java内部的String是Unicode编码, 既不是UTF-8, 也不是ISO-8859-1, 所以不能直接用String传送数据, 需要转换成byte数组, 类似于 this.someString.getBytes("ISO-8859-1");

4. Java内部的char类型也是Unicode编码, 同第三点一样, 所以需要转换成byte传输.

5. 常见数值型数据类型中, Java和 32-bit C所占字节数大多一样, 唯一需要注意的是long类型, Java是64位, 需要用int64_t相对应

6. Java已经提供了相当易用的类将常见数据类型封装为网络字节流, 或是相反, 从网络字节流中解析出数值.

例如, 写:

byte[] buf = new byte[100];
ByteBuffer bytebuf = ByteBuffer.wrap(buf);
bytebuf.putInt(0x10);
//还可以调用其它bytebuf.putXX函数
socket.getOutputStream().write(buf,0,4); //测试, 只写4个字节

例如, 读:

DataInputStream dis = new DataInputStream(socket.getInputStream());
dis.readByte();
dis.readInt();
byte[] recvbuf = new byte[10];
dis.readFully(recvbuf );

最后附一个  Java与 bit-32 C 的数据类型的比较, 以作参考

Type Java C
 short  2 bytes  2 bytes
 int  4 bytes  4 bytes
 long  8 bytes  4 bytes
 float  4 bytes  4 bytes
 double  8 bytes  8 bytes
 boolean  1 byte  N/A
 byte  1 byte  N/A
 char  2 bytes  1 byte

Socket网络通讯开发总结之:Java 与 C进行Socket通讯 + [备忘] Java和C之间的通讯的更多相关文章

  1. [备忘]java 静态块、非静态块、静态函数、构造函数 执行顺序

    原文链接:http://liqita.iteye.com/blog/1472717 java中经常有一些静态块,这是用来在生成类之前进行的初始化,无论java还C++语言中的static,都是最先初始 ...

  2. java 环境变量的设置,备忘

    新建系统变量JAVA_HOME 和CLASSPATH 变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.7.0变量名:CLASSPATH 变量值:.;%JAVA ...

  3. java中堆栈的一些理解备忘

    堆:用来存放对象的信息,同一个类存放各自的成员变量,共享对象的方法. 栈:用来保存局部变量的值,包括基本数据类型的值.保存类的实例(堆区对象的引用).保存加载方法的帧. 常量池:包含了一个类型所有的对 ...

  4. sanic官方文档解析之Custom Protocols(自定义协议)和Socket(网络套接字)

    1,Custom Protocol:自定义协议 温馨提示:自定义协议是一个高级用法,大多数的读者不需要用到此功能 通过特殊的自定义协议,你可以改变sanic的协议,自定义协议需要继承子类asyncio ...

  5. debian文本配置网络备忘:/etc/network/interfaces

    我装了wheezy有gnome3,xfce4: 郁闷的是,不论在gnome还是xfce4中 我都无法图形登录或者切换用户到root: 而且我无法在普通用户下图形修改网络配置: 我也搜索不到启用root ...

  6. 进程之间的通讯Queue简单应用

    #进程间通讯--Queue #Process有时需要通信的,操作系统提供了很多机制来实现进程之间的通讯 #而Queue就是其中一个 #1.Queue的使用 #可以使用multiprocessing模块 ...

  7. Socket网络通讯开发总结之:Java 与 C进行Socket通讯(转)

    先交待一下业务应用背景:服务端:移动交费系统:基于C语言的Unix系统客户端:增值服务系统:基于Java的软件系统通迅协议:采用TCP/IP协议,使用TCP以异步方式接入数据传输:基于Socket流的 ...

  8. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

  9. [dotnet core]使用Peach简化Socket网络通讯协议开发

    Peach是基于DotNetty的Socket网络通讯帮助类库,可以帮助开发者简化使用DotNetty,关于DotNetty可参考我之前的这篇文章. Peach内置实现了一个基于文本协议的Comman ...

随机推荐

  1. 关于django批量上传图片

    本来想一张一张上传的,但是明显会对客户造成不必要的麻烦,所以如果前台一次性上传五张十张的话,那就简单的多. 但是后台我数据库对于图片存储的字段只有一个,不可能有多少张照片就要多少个字段来存储.也就是说 ...

  2. HDU 5568 sequence2 区间dp+大数

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5568 题意: 求所有长度为k的严格升序子序列的个数. 题解: 令dp[i][k]表示以i结尾的长度为 ...

  3. FastDFS配置文件(tracker.conf)

    # ===========================基本配置==================================== # 该配置文件是否生效 # false:生效 # true: ...

  4. boost之bind,function,signal总结

    boost里的bind,function,signal三个组件都是对用函数做参数(其他算法也用函数做参数),对函数的某一项进行操作. bind主要是对函数参数的作用. function主要是对函数地址 ...

  5. Facebook 和 Google 如何激发工程师的创造力

    原文链接:http://kb.cnblogs.com/page/193450/ 今天终于“朝圣”了两个伟大的公司——Facebook和Google,对创造力和驱动力的来源有了更多的理解,尤其是对于典型 ...

  6. [poj 1741]Tree 点分治

    题意 求树上距离不超过k的点对数,边权<=1000 题解     点分治.     点分治的思想就是取一个树的重心,这种路径只有两种情况,就是经过和不经过这个重心,如果不经过重心就把树剖开递归处 ...

  7. 2011 Asia Fuzhou Regional Contest

    Xiangqi http://acm.hdu.edu.cn/showproblem.php?pid=4121 模拟,用高内聚低耦合的思想来写模拟题还是很好的,提高了函数的可重用性,程序的可读性,正确性 ...

  8. 一张思维导图说明jQuery的AJAX请求机制

    比文字描述清晰多了吧?而且越是复杂的逻辑,思维导图的作用就越大,同时对阅读源码也是一种快捷的方法. 看不清楚的话可以右键,在新标签页中打开图片,或者保存本地.

  9. WaitForTargetFPS

    WaitForTargetFPS,是关于帧数限制的,你可能开了垂直同步,其实是防止撕裂.先说撕裂,在显示器的帧缓存会被不同步的显卡的帧缓存给替换掉,导致显示器显示到一半的时候,内存被换掉,你看到上频是 ...

  10. 白话CSS3的新特性

    声明:这篇文章不是手册,所以不会说的很详细,只是告诉初学者CSS3显著的改进有啥,高手老手绕行. 一.在边框上的改进 1.可以给方框加圆角了,值越大越圆,解决了过去大方框的不美观 2.可以给控件加阴影 ...