C与java通讯

最近在做java和c的UDP通信,才发现自己的通信基础知识基本为0,汗一个。。不过还好,在大家的帮助下,终于完成了。。下面写下一些小的总结。
(1)字节序问题:这个是通讯的大问题。。前面几篇文章也转载了查阅到的一些资料。总的来说C一般使用的是小尾存储数据,而java使用大尾存储,所谓大尾存储就是数据高字节在前,低字节在后存储。而网络中的数据则都是大尾存储。另字符串在传输过程中不会发生变化,而int,long等数值类型的数据会经过根据大小尾进行存储传输。所以当java与c进行通信的时候,java一段数据基本不用进行大小尾转化,而c收到数据后要进行NToH转化,发送数据的时候也要进行HToN数据转化。再加上字符串,打成包传输即可。
(2)传输包问题:总所周知,传输数据不可能一个字节一个字节发送,没有意义,当然要打成代表一定意义的包进行发送,包就要有包头,包尾。比如下面包的定义:

消息结构

项目

说明

Message Header

消息头(所有消息公共包头)

Message Body

消息体

 

消息头格式Message Header

字段名

字节数

类型

描述

Total_Length  

4

Unsigned Integer

消息总长度(含消息头及消息体)

Command_Id

4

Unsigned Integer

命令或响应类型

Sequence_Id

4

Unsigned Integer

消息流水号,顺序累加,步长为1,循环使用(一对请求和应答消息的流水号必须相同)

Version

4

Unsigned Integer

表示,当前网站与AS核心代码通讯的版本号。目前的版本号为:0x0002


消息体如下:

发送请求:

字段名

字节数

类型

描述

AS服务器名称

22

Octet String

AS服务器名称

机构名称

22

Octet String

机构名称

起始日期

4

Unsigned Integer

证书有效起始日期

结束日期

4

Unsigned Integer

证书有效终结日期

 

响应

字段名

字节数

类型

描述

AS服务器名称

22

Octet String

AS服务器名称

机构名称

22

Octet String

机构名称

证书路径

128

Unsigned string

证书在本机存储路径

结果值

1

char

0:解析正确,1:解析错误

 

这样当发送的时候需要把消息头和消息体构建出来,并全部转化成byte数组,再进行传输。
再者对数据包发送的时候,是根据接口文件的。。也就是java和c通讯接口文件,自己定义的了,一致就行。这里面如上面包格式所示,都定义好了每个字段的长 度,那么当读取的时候也要根据这个长度进行读取。那么当实际的长度没有这么长怎么办呢?那就需要双方定义好填充字符,是使用空字符('\0')呢,还是空 格(' ')呢,c里面读取一般遇到空字符就停止。所以使用空字符会比较普遍一些。当java接收到数据后,也要根据找个字符解析出真正长度的字符串。比如使用下面函数去掉后面的空字符:
       private String getRealData(byte[] temp){
              String res = new String(temp);
              int end = res.indexOf('\0');
              String result = res.substring(0,end);
              return result;
       }
而java得到包之后,如何得到每个字段呢,这个没有别的办法了,只能一段一段的拷贝了。下面是我使用的拷贝方法:
private String getServerName() {
              byte[] temp = new byte[22];
               System.arraycopy(this.getRawData(), 1, temp, 0, temp.length);
              String encodeStr = getRealData(temp);
              return new String(Base64.decode(encodeStr.getBytes()));
       }
而c中则使用结构体就可以了。定义好结构体,接受的之后直接接受结构体,然后根据结构体读取,方便快捷,java这方面确实有点麻烦了。
(3)byte,string区别:本来以为传输的时候就是string类型字符串,原来根本不是一回事。网络上传输数据都是字节码,就是我们常说的ascII码的,对应到类型上就是byte类型的。而string只是java中一种对象而已。而且java中编码一般是unicode编码的,要进行和byte类型的转化。int和long类型的也要进行int2byte转化。
接收到数据之后,则要进行byte2int转化。且值得注意的是int转成byte并不是直接字符串的转化,比如123转成字符串就是123,但是转成byte就不是了。它要根据整数123所占的字节,得到每个字节的值,再转成byte数组。常用的转化函数有:
//int2byte
public static byte[] intToByte(int n) {
              byte[] b = new byte[4];
              b[0] = (byte) (n >> 24);
              b[1] = (byte) (n >> 16);
              b[2] = (byte) (n >> 8);
              b[3] = (byte) (n);
              return b;
       }

       public static void int2byte(int n, byte buf[], int offset) {
              buf[offset] = (byte) (n >> 24);
              buf[offset 1] = (byte) (n >> 16);
              buf[offset 2] = (byte) (n >> 8);
              buf[offset 3] = (byte) n;
       }

       // 字节类型转成int类型
       public static int byte2int(byte b[]) {
              return b[3] & 0xff | (b[2] & 0xff) << 8 | (b[1] & 0xff) << 16
                            | (b[0] & 0xff) << 24;
       }
//short2byte
public static byte[] short2byte(int n) {
              byte b[] = new byte[2];
              b[0] = (byte) (n >> 8);
              b[1] = (byte) n;
              return b;
       }
// long到byte的转换
       public static byte[] long2byte(long n) {
              byte b[] = new byte[8];
              b[0] = (byte) (int) (n >> 56);
              b[1] = (byte) (int) (n >> 48);
              b[2] = (byte) (int) (n >> 40);
              b[3] = (byte) (int) (n >> 32);
              b[4] = (byte) (int) (n >> 24);
              b[5] = (byte) (int) (n >> 16);
              b[6] = (byte) (int) (n >> 8);
              b[7] = (byte) (int) n;
              return b;
       }
等等,注意:这里只是进行普通的字节码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值