Java与C++复合使用还有其他方式(譬如:JNI的), 今天特地尝试了一种Socket的方式:
本代码展示了,java向C++发送一个Employee的Struct结构; 反向的转化碰到了一些问题:
譬如想将C++发送回来的byte[]转化String,但是不能直接用new String(byte[]), java会忽略掉数组中0(这个零在C++中刚好又是字符串结束的标志)
Java端代码(window7, jdk1.6):
- package tcp.test;
- import java.net.*;
- /**
- * 与c语言通信(java做client,c/c++做server,传送一个结构)
- *
- * @author kingfish
- * @version 1.0
- */
- public 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;
- }
- /**
- * 将byte数组转化成String
- */
- private static String toStr(byte[] valArr,int maxLen) {
- int index = 0;
- while(index < valArr.length && index < maxLen) {
- if(valArr[index] == 0) {
- break;
- }
- index++;
- }
- byte[] temp = new byte[index];
- System.arraycopy(valArr, 0, temp, 0, index);
- return new String(temp);
- }
- /**
- * 将低字节在前转为int,高字节在后的byte数组
- */
- private static int vtolh(byte[] bArr) {
- int n = 0;
- for(int i=0;i<bArr.length&&i<4;i++){
- int left = i*8;
- n+= (bArr[i] << left);
- }
- return n;
- }
- public String name = "";
- public int id = 0;
- public float salary = 0;
- /**
- * 将float转为低字节在前,高字节在后的byte数组
- */
- private static byte[] tolh(float f) {
- return tolh(Float.floatToRawIntBits(f));
- }
- private static Employee getEmployee(byte[] bArr) {
- String name = "";
- int id = 0;
- float salary = 0;
- byte[] temp = new byte[20];
- name = toStr(bArr,20);
- System.arraycopy(bArr, 20, temp, 0, 4);
- id = vtolh(temp);
- return new Employee(name, id, salary);
- }
- /**
- * 构造并转换
- */
- public Employee(String name, int id, float salary) {
- this.name = name;
- this.id = id;
- this.salary = 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 {
- int index = 0;
- byte[] receive = new byte[28];
- while(true){
- Socket sock = new Socket("127.0.0.1", 5050);
- System.out.println("send content: name=kingfish "+"value="+(1+index));
- sock.getOutputStream().write(new Employee("kingfish"+index, 1+index++, 10.99f + index).getbuf());
- sock.getInputStream().read(receive);
- Employee ee = getEmployee(receive);
- System.out.println(" response: name="+ee.name+" "+"value="+ee.id);
- sock.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- } // end
C++端代码(环境: window7, visual studio 2008):
- // SocketTest.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include "stdio.h"
- #include <WINSOCK2.H>
- #pragma comment(lib, "Ws2_32.lib")
- struct UserInfo {
- char UserName[20];
- int UserId;
- };
- struct Employee {
- UserInfo user;
- float salary;
- };
- int main(int argc, char* argv[]) {
- WSADATA wsaData;
- char buf[1024];
- int nBytes=1024, recvbytes;
- SOCKET Listening;
- SOCKET NewConnection;
- SOCKADDR_IN ServerAddr;
- SOCKADDR_IN ClientAddr;
- int ClientAddrLen=sizeof(ClientAddr);
- int Port = 5050;
- int c;
- WSAStartup(MAKEWORD(2,2),&wsaData);
- Listening = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
- ServerAddr.sin_family = AF_INET;
- ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- ServerAddr.sin_port = htons(Port);
- bind( Listening, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr) );
- listen( Listening, 5 );
- printf( "Wating accpet....\n" );
- while(true) {
- NewConnection = accept(Listening,(SOCKADDR *)&ClientAddr, &ClientAddrLen);
- printf( "Wating recv.....\n" );
- if( ( recvbytes=recv(NewConnection,buf,nBytes,0) ) == SOCKET_ERROR )
- {
- printf( "\nErrorcode=%d, Recv from client\n", WSAGetLastError() );
- return 0;
- }
- Employee *data = new Employee;
- data = (Employee *)&buf;
- printf( "Userid: %d Username: %s Salary: %f", data->user.UserId, data->user.UserName, data->salary );
- data->user.UserId = 007;
- strcpy(data->user.UserName, "Test");
- data->salary = 800;
- send( NewConnection, buf, recvbytes, 0 );
- }
- return 0;
- }