之前我实现了UDP通信,可以通过客户端发送信息,实现服务端接收。那么要实现数据的查找,还要引入sqlite3数据库。
SQLite3:是一种轻量级关系型数据库管理系统(可嵌入的数据库),可以在应用程序内部直接操作文件,不需要独立的进程。跨平台,零配置,体积小。
安装:sudo apt install sqlite3
一些基本命令:
创建(查看)数据库文件:sqlite3 mydata.db
查看当前数据库所有表:.tables
看数据:select * from XXX;
退出 .exit
为了实现客户端发送英文可以查询,需要先导入一个中英文的数据库,然后服务端接收,进行数据库的查找,将查找到的中文返回给服务端。
导入数据库:将excel文件改格式为CSV,导入目标文件下,在shell下
,mode csv 导入csv格式;.import XXX.csv dictionary;
可以通过查看数据 select * form XXX where english=’’;判断数据库有没有被导入。
准备好了数据库和UDP通信,接下来就是对UDP接收的代码进行优化,实现查询数据的发送。
服务端recvfrom到的英文会放在buf缓冲区中,在利用sqlite3中的exec函数族进行查找,返回值也在buf中,只需要对buf进行处理,就得到了查询到的中文。
同理,在客户端,recv服务端发出的buf就可以收到查询的中文。
下面是服务端部分代码:
void udp_main(const int fd, const struct sockaddr_in *addr) {
int rc;
int ret;
sqlite3 *db;
char buf[BUFSIZ]={};
char *sql_query,*errmsg;
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
if( (rc = sqlite3_open(DATABASE_NAME,&db)) ){
printf("[%s:%d]无法打开数据库:%s\n",__FUNCTION__,__LINE__,sqlite3_errmsg(db));
exit(0);
}
while(1){
do{
ret=recvfrom(fd,buf,BUFSIZ,0,(struct sockaddr *)&client_addr,&addrlen);
}while(ret<0 && errno == EINTR);
if(ret < 0)
ErrExit("recvfrom");
printf("[%s:%d]收到的数据:{%s}\n",__FUNCTION__,__LINE__,buf);
/*提取需要翻译的单词*/
int i=0;
char word[128]={};
for( i=0;isalpha(buf[i]) || buf[i] ==' ';i++){
word[i]=buf[i];
}
word[i]='\0';
buf[i]='\0';
/*用SQL语句进行查询*/
sql_query = sqlite3_mprintf("select * from dictionary where english like '%s'",buf);
rc = sqlite3_exec(db,sql_query,callback,buf,&errmsg);
if(rc !=SQLITE_OK){
sprintf(buf,"fail:%s\n",errmsg);
printf("[%s:%d]:{%s}\n",__FUNCTION__,__LINE__,buf);
sendto(fd,buf,strlen(buf)+1,0,(struct sockaddr *)&client_addr,addrlen);
sqlite3_free(errmsg);
continue;
}
sqlite3_free(sql_query);
printf("[%s:%d]查询结果:%s\n",__FUNCTION__,__LINE__,buf);
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1]='\0';
Savedata(word,buf);
sendto(fd,buf,strlen(buf)+1,0,(struct sockaddr *)&client_addr,addrlen);
}
sqlite3_close(db);
close(fd);
close(rc);
}
int callback(void *NotUsed, int argc, char **argv, char **ColName) {
char *buf = NotUsed;
if(argc == 2) {
/* 把查询到的字符串复制给buf */
strncpy(buf, argv[1], strlen(argv[1]) + 1 );//将第二个结果及中文输出
} else
buf[0] = '\0'; //如果失败就将字符串置空
/* 给字符串增加为'\0' */
buf[strlen(argv[1])] = '\n';
buf[strlen(argv[1])+1] = '\0';
return 0;
}
void Savedata(const char *word,const char *buf){
FILE *fp;
int linecount = 0;
time_t ctime;
struct tm *ctimestr;
char str[128]={};
if( (fp = fopen("serve_record.txt","a+") )== NULL)
ErrExit("fopen");
while( fgets(str,128,fp) != NULL){
if(str[strlen(str)-1] == '\n')
linecount++;
}
ctime = time(NULL);
ctimestr = localtime(&ctime);
printf("%d\t%04d-%02d-%02d %02d:%02d:%02d\t%s\t%s\n",
linecount,
ctimestr->tm_year+1900, ctimestr->tm_mon+1, ctimestr->tm_mday,
ctimestr->tm_hour, ctimestr->tm_min, ctimestr->tm_sec, word, buf);
fprintf(fp, "%d\t%04d-%02d-%02d %02d:%02d:%02d\t%s\t%s\n",
linecount,
ctimestr->tm_year+1900, ctimestr->tm_mon+1, ctimestr->tm_mday,
ctimestr->tm_hour, ctimestr->tm_min, ctimestr->tm_sec, word, buf);
fclose(fp);
}

5108

被折叠的 条评论
为什么被折叠?



