java程序和C/C++程序的通讯 收藏摘要:本文研究了数据存储格式中大尾小尾问题,根据此原理解决了Java程序和C/C++通讯及读取服务器端文件时的数据移植问题。 该问题起源于笔者设计的基于Web的远程测控系统。它的基本原理是:服务器端运行一VC编制的服务器程序,客户端使用Java applet;VC服务器程序接收到Java applet发送的命令后,采集各种信息,并将所有数据发向applet,实现了基于Web的远程温度、加速度的实时监控。 VC程序和Applet之间的通讯方式采用了基于TCP/IP协议的socket通讯,笔者不准备在socket的通讯本身进行过多的讲述,而将重点研究实时通讯中涉及到的数据移植问题。
基于Web的测试软件是由C++数据采集服务器程序和客户端Java显示程序两部分构成,前者用C++,后者Java语言,存在数据移植问题。因为 在计算机系统中,当包含数字的二进制文件从一个结构移到另一结构时,就出现大尾小尾问题。不同CPU在多字节数(如四字节int)存储时有两种方法,一种 方法叫小尾(little_endian),数据的低字节被放置在连续存储区的首位,另一种方法叫大尾(big_endian),数据的高字节被放置在连 续存储区的首位。Intel 80×86家族处理器是最后一个仍然坚持小尾的主要结构。所有其他的CPU结构(Motorola 680×0和所有RISC芯片)或者是纯粹的大尾或者是既适应大尾也适应小尾,大尾被认为是更符合逻辑的方法)。当数字由小尾处理器写入文件然后又由大尾 处理器读取(或者倒过来)时,数字就会被搞乱(除了0和-1)。 运用C++或C语言,数据在文件中的存储形式是与处理器相关的,这使得简单的数据文件的移植成为一个大问题。而Java作为平台独立语言,所有的数据都是以大尾形式存储到文件中,Java语言本身产生的数据文件无移植问题。但是它在与C/ C++通讯时还应注意, 举个例子:float型数据1.5在VC程序和Java程序中的表示如下:
但是,f并不等于1.5,必须将data接收到的字节流进行数据移植(小尾排序方式改为大尾排序),data[0]的值和data[3]值互换,data[1]的值和data[2]的值互换。
这样,得到了正确的结果。 笔者针对此问题设计了一个数据移植类WindowsStream,它的作用是把C/C++格式的数据转换成Java格式数据,使得Java程序可以 读取C/C++发送的数据和文件。该类将各种数据类型读入缓冲中(逐个字节读),然后在缓冲区中改变字节的排序方式,其源程序如下:
配合本Java客户程序(其源程序见最后)的UDP服务器程序(服务端口8888)(该程序可以在ftp//202.114.6.107 /incoming处下载或E_mailTome:windgf@263.net),在接收到客户端命令(此处设为“DAT”)后,将向客户端返回2K byte型数据,Java客户端使用UdpData的read方法接收。read方法中host表示运行UDP服务器程序的IP地址,buffer用于存 储接收到的数据,ch1用于存储转换后的short型数据,下面这个程序片断简要演示了UdpData的用法。
Java和C++程序在写文件时也使用了不同的数据格式,所以,Java程序不能从C++程序创建的文件直接读取二进制数据。在读取服务器端的.wav文件时,同样涉及到数据移植的问题,.wav的文件结构具有如下:
ch:记录通道数,hz:采样频率,bit:模数转换的位数,ds:文件的长度,wave:指向数据的指针。此处假定long int在C/C++中是四个字节,而在Java中为8个字节。 以下是类WavFile源文件,其read方法用于读取.wav文件,location标识.wav文件的URL,buffer是用于存储原始数据的缓存,ch1和ch2分别用于存储左右两通道的数据,
下面的程序片断演示了如何在java程序中使用WavFile读取.wav文件
根据前面的分析,笔者设计了一Java applet程序,成功读取服务器端.wav文件和接收UDP服务器程序发送的数据,并在applet的面版上进行显示。
|
|