自写项目——实现tesseract-ocr功能_初步socket实现
在安装好tesseract-ocr后,已经能够在本机上初步识别一些文字,但要把其搭在服务器上,就需要一些文件传输,这里采用socket编程,实现服务器与客户端的文件传输。
我做好了服务端,和客户端:
客户端上传图片文件到服务端,并选择要识别的语言,并接受到服务端传回的结果。
服务端安装了tesseract-ocr,接受客户端传送的图片文件,在服务端进行识别,并把结果传送到客户端。
这就是其大概的思路,下面上代码(已经加上注释!linux下验证通过):
客户端(client):
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#define BUFFER_SIZE 1024
//准备工作
int sockfd;//
char* IP = "192.168.30.3";//该地址请写测试服务器的IP,本机IP,回送地
short PORT = 10222;//端口号
typedef struct sockaddr SA;//类型转换
char filename[100];//客户端昵称
char langeuage[100];
//启动客户端,连接服务器
void init()
{
printf("OCR客户端开始启动\n");
sockfd = socket(AF_INET,SOCK_STREAM,0);//启动socket
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
if(connect(sockfd,(SA*)&addr,sizeof(addr))==-1){//向服务器请求建立链接
perror("无法连接到服务器");
printf("客户端启动失败\n");
exit(-1);
}
printf("客户端启动成功\n");
}
//开始通信
void start()
{
//发送消息
//发消息之前,启动一个线程,用来接受服务器发送过来的消息
// pthread_t pid;
// pthread_create(&pid,0,recv_thread,0);
// 打开文件并读取文件数据
char buffer[BUFFER_SIZE];
int file_size=0;
int sum=0;
FILE *fp = fopen(filename, "r");
fseek(fp, 0, SEEK_END);
file_size=ftell(fp);//得到文件大小
// printf("file_size=%d",file_size);
send(sockfd,&file_size,sizeof(int),0);// 把文件大小数据发送
fseek(fp, 0, SEEK_SET);
if(NULL == fp)
{
printf("File:%s Not Found\n", filename);
}
else
{
bzero(buffer, BUFFER_SIZE); //清空buffer
int length = 0;
// 每读取一段数据,便将其发送给客户端,循环直到文件读完为止
while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
if(send(sockfd, buffer, length, 0) < 0)//发送失败退出
{
printf("Send File:%s Failed./n", filename);
return ;
}
bzero(buffer, BUFFER_SIZE);
}
// 关闭文件
fclose(fp);
/****************用户提示区***************/
printf("******************************\n");
printf("File:%s Transfer Successful!\n", filename);
printf("******************************\n\n");
printf("系统正在识别,请稍后......\n");
printf("这可能需要一段时间........\n\n");
/*****************************************/
fp = fopen("result.txt", "wt");
//printf("flag\n\n");
if(NULL == fp)
{
printf("File:\t%s Can Not Open To Write\n", "result.txt");
exit(1);
}
// 从服务器接收数据到buffer中
// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止
bzero(buffer, BUFFER_SIZE);
while((length = recv(sockfd, buffer, BUFFER_SIZE, 0)) > 0)
{
sum+=length;
printf("->已接受%d kb\n",sum);
//printf("length=%d\n",length);
if(fwrite(buffer, sizeof(char), length, fp)<0)//写入文件中
{
printf("Write file result.txt Failed.");
return ;
}
bzero(buffer, BUFFER_SIZE);
}
//若服务端解析图片错误,就不会发送完整的result.txt 则输出提示信息。
printf("\n******************************\n");
if(sum>3) printf("Receive File:\t%s From Server IP Successful!\n", filename);
else printf("The image is wrong!\n");
printf("******************************\n");
printf("\n文档已成功接受!请在本目录下的result.txt下查看!\n");
// 接收成功后,关闭文件,关闭socket
fclose(fp);
}
close(sockfd);//关闭socket
}
void sig_close()
{
//关闭客户端的描述符
close(sockfd);
exit(0);
}
int main()
{
int type;
signal(SIGINT,sig_close);//关闭CTRL+C
init();//启动并连接服务器
printf("\n请输入文件名:");
scanf("%s",filename);
printf("语言类型对应编号:\n");
printf("English :1\t中文简体:2\n");
printf("中文繁体:3\tFrancd :4\n\n");
printf("请输入要识别的语言类型(请务必填对应的编号):");
scanf("%d",&type);
switch(type)
{
case 1: strcpy(langeuage,"eng"); break;
case 2: strcpy(langeuage,"chi_sim"); break;
case 3: strcpy(langeuage,"chi_tra"); break;
case 4: strcpy(langeuage,"fra"); break;
default: strcpy(langeuage,"eng");
}
send(sockfd,filename,sizeof(filename),0);//把图片名字传到服务器
send(sockfd,langeuage,sizeof(langeuage),0);//把语言类型传到服务器
start();//开始与服务器进行通信。
return 0;
}
服务端(server):
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#define BUFFER_SIZE 1024
char buffer[BUFFER_SIZE];
//准备工作
int sockfd;//
char* IP = "192.168.30.3";//服务器IP
short PORT = 10222;//端口号
typedef struct sockaddr SA;//类型转换
//初始化服务器的网络,创建socket
void init()
{
printf("OCR服务器开始启动..\n");
sockfd = socket(AF_INET,SOCK_STREAM,0);//启动socket
if(sockfd == -1){
perror("创建socket失败");
printf("服务器启动失败\n");
exit(-1);
}
//准备网络通信地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);
if(bind(sockfd,(SA*)&addr,sizeof(addr))==-1){//绑定服务器
perror("绑定失败");
printf("服务器启动失败\n");
exit(-1);
}
printf("成功绑定\n");
//设置监听
if(listen(sockfd,10)==-1){
perror("设置监听失败");
printf("服务器启动失败\n");
exit(-1);
}
printf("设置监听成功\n");
printf("初始化服务器成功\n");
//等待客户端链接,放到另一个函数中
}
void* service_thread(void* p)
{
int sum=0;
int file_size=0;
int fd = *(int*)p; //拿到标记客户端的sockfd
//printf("pthread=%d\n",fd);//输出测试
char filename[100] ={0};
int length = 0;
char shell_order[200]={0};
char langeuage[100];
recv(fd,filename,sizeof(filename),0); //得到文件名字
recv(fd,langeuage,sizeof(langeuage),0); //得到语言类型
recv(fd,&file_size,sizeof(int),0); //得到文件大小
/******************************从服务端接受文件*********************************/
FILE *fp = fopen(filename, "wt");
if(NULL == fp)
{
printf("File:\t%s Can Not Open To Write\n", filename);
exit(1);
}
// 从服务器接收数据到buffer中
// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止
bzero(buffer, BUFFER_SIZE);
//printf("file_size=%d\n",file_size);
while((length = recv(fd, buffer, BUFFER_SIZE, 0)) > 0)//接受文件
{
//printf("length=%d\n",length);
sum+=length;
if(file_size==sum) break;
if(fwrite(buffer, sizeof(char), length, fp)<0)//写文件
{
printf("Write %s File Failed!",filename);
return NULL;
}
bzero(buffer, BUFFER_SIZE);
}
// 接收成功后,关闭文件,关闭socket
printf("Receive File:\t%s From Server IP Successful!\n", filename);
fclose(fp);
/***********************************************************/
/**************************调用shell命令行语句*********************************/
sprintf(shell_order,"tesseract %s result -l %s",filename,langeuage);
system(shell_order);
/******************************************************************************/
/************************向客户端发送文件****************************/
fp=fopen("result.txt","r");
if(NULL == fp)
printf("File:%s Not Found\n","result.txt");
else
{
bzero(buffer,BUFFER_SIZE);
while((length = fread(buffer,sizeof(char),BUFFER_SIZE,fp)) > 0)
{
if(send(fd,buffer,length,0)<0)
{
printf("Send File: %s Failed",filename);
return NULL;
}
bzero(buffer, BUFFER_SIZE);
}
// 关闭文件
fclose(fp);
printf("File:%s Transfer Successful!\n", "result.txt");
}
/*******************************************************/
close(fd);//关闭socket
}
//等待客户端的连接,启动服务器的服务
void service()
{
printf("服务器开始服务\n");
while(1)//一直循环,等待客户端链接
{
struct sockaddr_in fromaddr;
socklen_t len = sizeof(fromaddr);
int fd = accept(sockfd,(SA*)&fromaddr,&len);
if(fd == -1)
{
printf("客户端链接出错\n");
continue;//继续循环,处理连接
}
//如果客户端成功连接上
printf("fd=%d\n",fd);//测试
//启动线程
pthread_t pid;
pthread_create(&pid,0,service_thread,&fd);
}
}
void signal_close(int signal_num){
//关闭服务器前 关闭服务器的socket
close(sockfd);
printf("服务器已经关闭\n");
exit(1);
}
int main()
{
signal(SIGINT,signal_close);//退出CTRL+C
init();//初始化服务器
service();//服务器开始运行
return 0;
}
这里需要注意,服务端搭到服务器上,而且保证服务器已经安装了tesseract-ocr,安装教程在这里:http://blog.csdn.net/chudongfang2015/article/details/51866379
如果需要在本机测试,只需把服务端和客户端的IP都改为:127.0.0.1(本地环回)