项目需要,文件拼接检查这块使用的c语言完成的,项目是java的项目,考虑过jni调用,但存在c代码异常导致jvm崩溃问题,故采用thrift进行调用,保证java项目运行稳定,
拼接检查的接口是
#define FILE_CONCAT_DETECTION_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct file_concat_entry
{
char *type;
off_t beg_pos;
off_t end_pos;
};
/**
* @brief file_concat_detection_buf
* @param buf
* @param len
* @param off
* @param entries
* @return 出错返回-1, 其它表示entries的数量, 用户需要free entries避免内存泄露
*/
int file_concat_detection_buf(char *buf, off_t len, off_t off, struct file_concat_entry **entries);
int file_concat_detection(char *pathname, off_t off, struct file_concat_entry **entries);
#ifdef __cplusplus
}
#endif
#endif // FILE_CONCAT_DETECTION_H
thrift接口为
namespace cpp FileConcat
// 定义错误异常
exception FileConcatError {
1: string message
}
// 定义文件合并条目结构
struct FileConcatEntry {
1: string type, // 使用 string 代替 char*
2: i64 beg_pos, // 使用 i64 代替 off_t
3: i64 end_pos // 使用 i64 代替 off_t
}
// 定义服务
service FileConcatService {
// 文件合并检测
list<FileConcatEntry> detection_buf(1: binary buf, 2: i64 len, 3: i64 off) throws (1: FileConcatError e);
list<FileConcatEntry> detection(1: string pathname, 2: i64 off) throws (1: FileConcatError e);
}
开发环境是UOS,首先按照thrift相关,boost在另一台机器上只安装了libboost-dev,没有问题
sudo apt install thrift-compiler
sudo apt install libthrift-dev
sudo apt install libboost-all-dev
执行 thrift --gen cpp FileConcat.thrift,执行完成后生成gen-cpp目录,里面有几个.cpp和.h文件,我这不的机器上thrift版本
另一个debian的机器thrift按照的版本是0.17.0,gen-cpp里面的文件有区别。
编写server端的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include "gen-cpp/FileConcatService.h"
#include "detector.h"
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace FileConcat;
class FileConcatServiceHandler : public FileConcatServiceIf {
public:
// Implement the file_concat_detection_buf method
void detection_buf(std::vector<FileConcatEntry> & _return, const std::string& buf, const int64_t len, const int64_t off) override {
printf("detect buf strlen:%d, len: %ld, off: %ld\n", strlen(buf.c_str()), len, off);
struct file_concat_entry *centries = NULL;
int num_entries = file_concat_detection_buf((char *)buf.c_str(), len, off, ¢ries);
if (num_entries == -1)
{
printf("file concat dection error");
FileConcatError e;
e.message = "file concat dection error.";
throw e;
}
for (int i=0; i<num_entries; i++)
{
printf("\tfind file: %s, beg: %ld, end: %ld, size: %ld\n", centries[i].type, centries[i].beg_pos, centries[i].end_pos, centries[i].end_pos-centries[i].beg_pos);
FileConcatEntry entry;
entry.beg_pos = centries[i].beg_pos;
entry.end_pos = centries[i].end_pos;
entry.type = centries[i].type;
_return.push_back(entry);
}
free(centries);
}
// Implement the file_concat_detection method
void detection(std::vector<FileConcatEntry> & _return, const std::string& pathname, const int64_t off) override {
struct file_concat_entry *centries = NULL;
int num_entries = file_concat_detection((char *)pathname.c_str(), off, ¢ries);
if (num_entries == -1)
{
printf("file concat dection error");
FileConcatError e;
e.message = "file concat dection error.";
throw e; // Throw exception on error
}
printf("file concat dectect: %s, off: %ld\n", pathname.c_str(), off);
for (int i=0; i<num_entries; i++)
{
printf("\tfind file: %s, beg: %ld, end: %ld, size: %ld\n", centries[i].type, centries[i].beg_pos, centries[i].end_pos, centries[i].end_pos-centries[i].beg_pos);
FileConcatEntry entry;
entry.beg_pos = centries[i].beg_pos;
entry.end_pos = centries[i].end_pos;
entry.type = centries[i].type;
_return.push_back(entry);
}
free(centries);
}
};
int main(int argc, char** argv) {
int port = 9090;
::std::shared_ptr<FileConcatServiceHandler> handler(new FileConcatServiceHandler());
::std::shared_ptr<TProcessor> processor(new FileConcatServiceProcessor(handler));
::std::shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
::std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
::std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
printf("Starting the server on port %d...\n", port);
server.serve();
return 0;
}
使用g++做为编译器,链接thrift库
g++ FileConcatServer.cpp gen-cpp/FileConcatService.cpp gen-cpp/FileConcat_constants.cpp gen-cpp/FileConcat_types.cpp -o ../bin/fileconcatdetectionserver -I/usr/include/thrift -lthrift -L../bin -lfileconcatdetection
得到fileconcatdetectionserver可执行程序,运行如下
下面编写java端的client代码,
首先是执行thrift --gen java FileConcat.thrift,执行完后产生gen-java目录,里面有三个java文件,复制到项目中
pom文件中添加thrift依赖
<dependencies>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.9.3</version>
</dependency>
</dependencies>
编写java代码
import org.apache.thrift.TException;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.protocol.TBinaryProtocol;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world shit!");
TTransport transport = null;
try {
transport = new TSocket("localhost", 9090);
transport.open();
TBinaryProtocol protocol = new TBinaryProtocol(transport);
FileConcatService.Client client = new FileConcatService.Client(protocol);
// 调用服务
// int result = client.detection_buf("buffer data", 100, 0, entries);
// System.out.println("Result: " + result);
byte[] byteArray = new byte[]{1, 2, 3, 4, 5}; // 示例 byte 数组
// 将 byte[] 转换为 ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
List<FileConcatEntry> r = client.detection_buf(byteBuffer, 5, 5);
List<FileConcatEntry> result = client.detection("/home/xxxx/Desktop/SpFileInspector/bin/hello_rar_test_doc.rar", 0);
System.out.println("Result: ");
for (FileConcatEntry entry: result)
{
System.out.println("type: " + entry.getType()+" ,beg:" + entry.getBeg_pos()+" ,end:"+entry.getEnd_pos());
}
} catch (TException e) {
e.printStackTrace();
} finally {
if (transport != null) {
transport.close();
}
}
}
}
java运行效果
c++的server运行结果