曙海教育集团论坛开发语言培训专区C++语言开发 → 在Java与C程序间进行socket通信的讨论


  共有5656人关注过本帖树形打印

主题:在Java与C程序间进行socket通信的讨论

美女呀,离线,留言给我吧!
wangxinxin
  1楼 个性首页 | 博客 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:青蜂侠 帖子:1393 积分:14038 威望:0 精华:0 注册:2010-11-12 11:08:23
在Java与C程序间进行socket通信的讨论  发帖心情 Post By:2010-12-10 14:34:59

1. 背景

  使用socket在Java程序与C程序间进行进程间通信。本文主要描述了在同C程序进行通信的Client端的Java实现功能。

  1.1. 使用的语言

  Client端:Java,JVM(JDK1.3)

  Server端:C,UNIX(Sun Solaris)

  1.2. 讨论范围

  数据发送:只涉及到Java中int整型系列的讨论,包括byte,short,int。

  数据接受:涉及到byte,short,int,long,float,double,char。

  1.3.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

  2. 实现

  输出流:使用OutputStream流发送数据到C程序端。

  输入流:使用DataInputStream流从C程序端接受数据

  2.1. 数据发送

  由于DataOutputStream流对于Java各个基本数据类型都相应地提供了“写”方法,如wrightShort和wrightInt等,因此当进行进程间通信(sockect通信)时,我们总是优先考虑使用DataOutputStream流。

  下面我们对DataOutputStream流及其成员方法进行分析:

  2.1.1. DataOutputStream流

  DataOutputStream流实现了接口DataOutput。

  本文只讨论writeByte(int v)、writeShort(int v)和writeInt(int v)部分(这是因为我们需要发送的数据只涉及到int,short和byte,其它的long,double等则不在这里介绍),而且它们都有一个共同的特征,即唯一的int类型的输入参数。

  这些成员方法的功能描述也为我们以后手动进行字节顺序转换,提供了理论依据。

  2.1.2.

  网络字节顺序

  规定:网络上传输的数据统一采用Big Endian格式(即“高字节在前”),我们称之为“网络字节顺序”(network byte order)。

  Big Endian格式:

  高字节 低字节

  1 2 3 4

  Byte[0] byte[1] byte[2] byte[3]输出缓冲区

  因此,无论本机字节顺序采用的那种顺序,在发送到网络之前都要转化为网络字节顺序,才能进行传输。特别是在Java与C两种不同语言的应用程序间进行通信时,这一点优为重要。(若是两个Java程序间通信时可能只要保证接受与发送采用相同的字节顺序,则可以不进行转换格式,但这种做法并不好,不具有良好的移植性)

  2.1.3. 数据发送:手动字节转换 / writeInt方法

  以writeInt(int v)为例进行描述:

  阅读DataOutput的writeInt(int v)方法的文档可知:

  使用writeInt方法可以写一个4-byte的int值v到输出流,其字节顺序为:

  (byte)(0xff & (v >> 24)) byte[0] 高字节

  (byte)(0xff & (v >> 16)) byte[1]

  (byte)(0xff & (v >> 8)) byte[2]

  (byte)(0xff & v) byte[3] 低字节

  这样的字节顺序为Big Endian格式,标准的“网络字节顺序”。

  但是在实际工作中输出流采用DataOutputStream.readInt(int)方法时写数据出错,需要自己手动按照以上所说的对需要写的v值进行转换(通过移位完成),转换的代码如下所示,可参见程序SocketClient.java中的ByteConverter.intToByte()方法。

  static public final byte[] intToByte(

  int value, int offset, int length, byte[] buffer)

  { // High byte first on network

  for (int i=0,j=length-1; i<length; i++,j--) {

  if ( j+offset >= 0 && j+offset < 1024 ) {

  buffer[j+offset] = (byte)( (value >> i*8) & 0xFF );

  } else {

  System.out.println (

  "Array index out of the bounds:Index=" + (j+offset) );

  }

  }

  return buffer;

  }

  2.2. 数据接收

  同数据发送相同,由于DataInputStream流对于Java各个基本数据类型都相应地提供了“读”方法,如readShort和readInt等,因此当进行进程间通信(sockect通信)时,我们总是优先考虑使用DataInputStream流。

  而与数据发送不同的是,DataInputStream下的成员方法经实际测试,“基本上可以”根据数据类型正确读出相应的数值。

  但并非完美,特别是与不同语言的应用程序进行通信时(如C)。

  根据表1(Java与C的数据类型的比较)可知:

  (1)long型的字节数在Java和C中相差4个字节:

  因此由readLong方法读来的数值应进行带符号的右移32(4-byte)位才能得到在C程序中相应的long型数值。

  Type Java C

  long 8-Byte 4-Byte

  (2)由于Java中的char型为2个字节,C中的char型为1个字节,因此不能使用readChar方法来读取C程序中的char数值。

  然而在Java中byte型为1个字节长,因此可以使用readByte方法得到C程序中的char型数值。

  Type Java C

  byte 1-Byte N/A

  char 2-Byte 1-Byte

  最近一个项目中c/c++代码和java代码通信,c那边用的是UINT类型,穿过来时4个字节,在这边java要把这4个字节转换成数值。这里就出现了一个java和c数值类型存储顺序不同的问题了。

  从微观上来看,也就是从单个byte来看,在c中和在java中存放的顺序是一样的,例如31在c中表示为0x1F(从左往右输出表示),在java中也是如此。但是如果从宏观,也就是每个byte之间的顺序,java和c就大不一样了。从宏观来说java也是高高低低,高位放左边低位放右边,但是c中刚好相反。

  如果在c中,31L的16进制从左往右输出结果是1F00000000000000,java中是000000000000001F。

支持(0中立(0反对(0单帖管理 | 引用 | 回复 回到顶部

返回版面帖子列表

在Java与C程序间进行socket通信的讨论








签名