java与c通信实现方案
来源:互联网 发布:js给标签添加style 编辑:程序博客网 时间:2024/06/13 10:06
1、源代码下载
java2c
2、介绍
Java与c通信,最大的问题就是Java数据和c数据的转换问题。最近我做的项目就是java与c通过蓝牙通信,难点就是java数据结构和c结构体数据的转换问题。
通过几天的研究,实际上这个问题还是比较容易解决的,并以java自制了一个自动转换两者数据结构的工具。
Java和c两者通信都是通过流获取以及发送字节,只需要将数据结构解析成对应语言平台的字节数组,以及字节数组组装成对应语言平台的数据结构即可。
3、代码
Java工具使用方法如下
/** * 结构体定义 */public class TestBean {// typedef struct Books// {// char title[10];// char name;// int int_id[2];// unsigned short int short_id;// float book_id;// }; @TXConvertData(index=0,dataType=TXDataEnum.TXChar,arrayLength=10) private char[] title; @TXConvertData(index=1,dataType=TXDataEnum.TXChar) private char name; @TXConvertData(index=2,dataType=TXDataEnum.TXInt,arrayLength=2) private int[] int_id; @TXConvertData(index=3,dataType=TXDataEnum.TXShortInt) private short short_id; @TXConvertData(index=4,dataType=TXDataEnum.TXFloat) private float book_id; public char[] getTitle() { return title; } public void setTitle(char[] title) { this.title = title; } public char getName() { return name; } public void setName(char name) { this.name = name; } public int[] getInt_id() { return int_id; } public void setInt_id(int[] int_id) { this.int_id = int_id; } public short getShort_id() { return short_id; } public void setShort_id(short short_id) { this.short_id = short_id; } public float getBook_id() { return book_id; } public void setBook_id(float book_id) { this.book_id = book_id; }}/** * 与c通信 */public class DoTest { public static void main(String[] args) throws Exception { // 创建一个数据转换工具对象 TXDataReader<TestBean> reader = new TXDataReader<TestBean>(TestBean.class); SocketAddress address = new InetSocketAddress("127.0.0.1", 8888); Socket socket = new Socket(); socket.connect(address); OutputStream out = socket.getOutputStream(); InputStream in = socket.getInputStream(); TestBean sendData = getBean(); // 将java对象转为c结构体的字节数组并发送 out.write(reader.convertToByte(sendData)); // 获取对应c结构体的字节长度 int len = reader.getDataLength(); byte[] buffer = new byte[len]; in.read(buffer); // 将c结构体字节数字转为java对象 TestBean recv = reader.convertToObject(buffer); console(recv); out.close(); socket.close(); } private static TestBean getBean(){ TestBean data = new TestBean(); // 字符串最后一个内容后必须是0,即字符串结束符 data.setTitle(new char[]{'h','e','l','l','o','w','o','r','l',0}); data.setName('s'); data.setInt_id(new int[]{123,456}); data.setShort_id((short)32767); data.setBook_id(3.14f); return data; } private static void console(TestBean data){ System.out.println("title:"+new String(data.getTitle())); System.out.println("name:"+data.getName()); System.out.println("short_id:"+data.getShort_id()); System.out.println("int_id[0]:"+data.getInt_id()[0]); System.out.println("int_id[1]:"+data.getInt_id()[1]); System.out.println("book_id:"+data.getBook_id()); }}
c代码
// TestSocketServer.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include <winsock2.h>#include <string.h>#pragma comment(lib,"ws2_32.lib")// 结构体定义typedef struct Books{ char title[10]; char name; //char test; int int_id[2]; unsigned short int short_id; float book_id;};int main(int argc, char* argv[]){ //初始化WSA WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; } //创建套接字 SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (slisten == INVALID_SOCKET) { printf("socket error !"); return 0; } //绑定IP和端口 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind error !"); } //开始监听 if (listen(slisten, 5) == SOCKET_ERROR) { printf("listen error !"); return 0; } //循环接收数据 SOCKET sClient; sockaddr_in remoteAddr; int nAddrlen = sizeof(remoteAddr); char revData[255]; while (true) { printf("\n等待连接...\n"); sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen); if (sClient == INVALID_SOCKET) { printf("accept error !"); continue; } printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr)); //接收数据 struct Books revBook; int ret = recv(sClient, revData, sizeof(Books), 0); if (ret > 0) { for(int i=0;i<sizeof(Books);i++){ printf("%d,",revData[i]); } printf("\n"); memcpy(&revBook, revData, sizeof(revBook)); printf("title:%s\n",revBook.title); printf("name:%c\n",revBook.name); printf("short_id:%d\n",revBook.short_id); printf("int_id[0]:%d\n",revBook.int_id[0]); printf("int_id[1]:%d\n",revBook.int_id[1]); printf("book_id:%f\n",revBook.book_id); } struct Books book; strcpy_s(book.title, "hello-c1"); book.name = 'a'; book.int_id[0] = 253; book.int_id[1] = 13; book.book_id = 22.2; book.short_id = -34; char snd_buf[sizeof(book)]; memset(snd_buf, 0, sizeof(book)); memcpy(snd_buf, &book, sizeof(book)); printf("\nlen:%d\n",sizeof(book)); printf("\nlen:%d\n",sizeof(snd_buf)); send(sClient, snd_buf, sizeof(snd_buf), 0); printf("发送:\n"); for(int i=0;i<sizeof(snd_buf);i++){ printf("%d,",snd_buf[i]); } closesocket(sClient); } closesocket(slisten); WSACleanup(); return 0;}
c控制台输出:
java控制台输出:
如图,成功自动将java对象转换为c结构体,以及将c结构体转换为java对象。
4、注意事项
方法com.wxtx.java2c.reflect.TXDataReader.needAlign(int, int)的作用是c结构体中的字节对齐功能。默认是按结构体中最长的字段进行字节对齐。例如例子中最长字段时float类型的book_id,所以以4字节对齐。
实际情况中c可能是其他对齐方式,根据需要可以修改该方法。
注解@TXConvertData 的使用方式:
@TXConvertData(index=0,dataType=TXDataEnum.TXChar,arrayLength=10)private char[] title;
- index表示被注解的字段在c结构体中的序号(从0开始计数);
- dataType表示被注解字段的数据类型,分别有TXDataEnum.TXInt,TXDataEnum.TXShortInt,TXDataEnum.TXChar,TXDataEnum.TXFloat。因为这次项目中涉及到的数据类型就这4种,所以也就没有什么动力在添加double以及其他的数据类型。至于结构体中嵌套结构体的情况,只需要进行递归解析即可,有需求的小伙伴自行修改工具代码吧,哈哈哈;
- arrayLength表示被注解字段的数组长度,如果该字段不是数组,则不需要使用该注解属性
阅读全文
0 0
- java与c通信实现方案
- java与c间通信
- java 与 c 的通信
- Java与C/C++异构平台的本地通信 实现java与硬件打交道
- Android中实现Native与H5的通信方案汇总
- 实现PHP,.NET, C#, JAVA, Python, Ruby,C(++) 与websocket 实时通信
- P2P通信原理与实现(C++)
- P2P通信原理与实现(C++)
- P2P通信原理与实现(C++)
- java socket 与linux c通信问题
- java socket与C语言通信
- java与c/c++进行socket通信
- Java与C之间的socket通信
- Java与C之间的socket通信
- Java与C之间的socket通信
- java与C之间的通信
- java与C进行socket通信中的通信异常问题
- Socket 通信实现 Flash 与Java连接
- nginx
- Hi3531与Hi3520 GPIO口的对比及驱动的修改
- 上线之后客户端自动刷新
- Linux进程通信之共享内存-shmget shmat
- 关于realloc的使用与分析
- java与c通信实现方案
- Studing Day3
- Android自定义View,paint+canvas的使用
- 51nod 1117聪明的木匠-贪心算法
- poj日记(1017)——贪心算法
- matlab自带机器学习算法
- Windows 7
- Tensorflow在Windows下的安装+各种错误解决
- OKHttp