Linux应用之在线词典-数据库的实现

之前我实现了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);
}
 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值