【在线词典】项目实现

15_Dictionary

在线词典

搭建客户端-服务器架构

准备必要的资源

整理原始数据

整理英汉双语对照表,将XLSX格式转换成CSV格式,准备好vocabulary_list.csv文件备用
注意:CSV格式的文件必须使用UTF-8的字符集;

建立mydatabase.db数据库,并创建dictionary表;

shell命令行终端输入sqlite3 mydatabase.db

create table dictionary (
English text not null,
Chinese text not null);

sqlite3当中CSV格式的导入

.mode csv
.import vocabulary_list.csv dictionary

查询数据

select * from dictionary where English='main';

如果显示如下信息表示配置成功:

main,"a.主要的,最重要的"

在这里插入图片描述

实现服务端代码:

udp.h

包含必要的头文件,定义必要的宏,定义函数指针

#ifndef _UDP_H_
#define _UDP_H_#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <errno.h>
#include <arpa/inet.h>#define ErrExit(msg) printf("[%s:%d]%s:%s", __FUNCTION__, __LINE__,msg, strerror(errno)), exit(EXIT_FAILURE)#endif

udp.c

实现UDP通信,预留udp_main接口

#include "udp.h"extern void udp_main(const int fd, const struct sockaddr_in *addr);int main(int argc, const char *argv[])
{/* 1.检查参数 */if(argc < 3) {printf("[%s][addr][port]\n", argv[0]);exit(EXIT_FAILURE);}/* 2.创建数据报套接字 */int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd < 0)ErrExit("socket");/* 3.设置通信结构体 */struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons( atoi(argv[2]) );if( inet_aton(argv[1], &addr.sin_addr) == 0) {printf("[%s:%d] Invalid address\n", __FUNCTION__, __LINE__);exit(EXIT_FAILURE);}/* 4.绑定通信结构体 */if( bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) )ErrExit("bind");/* 5.处理客户端数据 */udp_main(fd, &addr);/* 6.关闭套接字 */close(fd);return 0;
}

udp_main.c

预留的客户端数据处理接口

#include "udp.h"/* 其他必要的环境已封装好了,只需要实现与客户端的交互即可* 这里的fd是服务端的socket,* addr是服务端的地址*/
void udp_main(const int fd, const struct sockaddr_in *addr) {printf("udp main test.\n");
}

实现词典查询功能

在文件udp_main.c实现词典查询功能

#include "udp.h"
#include <ctype.h>
#include <sqlite3.h>#define DATABASE_NAME "mydatabase.db"int callback(void *, int, char **, char **);/* 其他必要的环境已封装好了,只需要实现与客户端的交互即可* 这里的fd是服务端的socket,* addr是服务端的地址*/
void udp_main(const int fd, const struct sockaddr_in *addr) {int ret = 0, rc;struct sockaddr_in client_addr;socklen_t addrlen = sizeof(client_addr);sqlite3 *db;char buf[BUFSIZ] = {};char *sql_query, *errmsg;/* 1.打开数据库 */if( (rc = sqlite3_open(DATABASE_NAME, &db) ) ) {printf("[%s:%d]无法打开数据库: %s\n", __FUNCTION__, __LINE__, sqlite3_errmsg(db) );exit(0);}/* 2.循环处理客户端数据 */while(1) {/* 2.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);/* 2.2.提取需要翻译的单词 */for(ret = 0; isalpha(buf[ret]) || buf[ret] == ' '; ret++);buf[ret] = '\0';/* 2.3.用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, "查询失败:%s\n", errmsg);printf("[%s:%d]%s", __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);sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&client_addr, addrlen);}sqlite3_close(db);/* 3.关闭数据库,关闭fd,并且退出程序 */close(fd);
}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 );} elsebuf[0] = '\0'; //如果失败就将字符串置空/* 将换行符替换为'\0' */buf[strlen(argv[1])] = '\n';buf[strlen(argv[1])+1] = '\0';return 0;
}

实现用户操作和服务端交互过程

接下来我们把文件组织成如下形式(执行tree命令可以看到):
在这里插入图片描述

备注:如果没安装:可以使用sudo apt-get install tree命令进行安装

设置环境变量

编辑.bashrc文件
执行sudo vim ~/.bashrc打开家目录下的.bashrc在文件末尾加上如下两句:

export DICTIONARY_SERVER_HOST='127.0.0.1'
export DICTIONARY_SERVER_PORT='8888'

在这里插入图片描述
然后再执行source ~/.bashrc让.bashrc生效
最后执行env | grep DICTIONARY,如果能看到我们刚设置的命令表示环境变量生效了
在这里插入图片描述

connect函数是否可以用在UDP通信当中?

在UDP通信中,使用connect()函数发出“虚拟连接请求”,以便建立虚拟连接。通过调用connect()函数,可以将UDP套接字绑定到目标IP地址和端口上,从而为UDP数据报提供一个默认的发送目的地。这样,在后续的send()函数调用中,就不需要再指定IP地址和端口。
但是,需要注意的是,在UDP通信中,由于不存在真正的连接,因此connect()函数并不会像TCP中那样进行三次握手。它只是在内核中存储了该套接字的目标地址,并在后续的send()或recv()函数调用中使用该目标地址。
下面是一个示例代码片段,展示如何在UDP通信中使用connect()函数:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>#define BUF_SIZE 1024int main(int argc, char *argv[]) {if (argc != 3) {printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd == -1) {perror("socket");exit(1);}struct sockaddr_in dest_addr;memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.sin_family = AF_INET;dest_addr.sin_addr.s_addr = inet_addr(argv[1]);dest_addr.sin_port = htons(atoi(argv[2]));if (connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) == -1) {perror("connect");exit(1);}char buf[BUF_SIZE];printf("Enter message: ");fgets(buf, BUF_SIZE, stdin);if (send(sockfd, buf, strlen(buf), 0) == -1) {perror("send");exit(1);}close(sockfd);return 0;
}

编写客户端代码

这里我们对client下的文件进行编辑:

udp.c

#include "udp.h"extern void udp_main(const int fd, const char *argv);int main(int argc, const char *argv[])
{/* 获取环境变量DICTIONARY_SERVER_PORT */char *port = getenv("DICTIONARY_SERVER_PORT");if(port == NULL) {printf("没有发现环境变量[DICTIONARY_SERVER_PORT]\n");exit(EXIT_FAILURE);}/* 获取环境变量DICTIONARY_SERVER_HOST */char *host = getenv("DICTIONARY_SERVER_HOST");if(port == NULL) {printf("没有发现环境变量[DICTIONARY_SERVER_HOST]\n");exit(EXIT_FAILURE);}/* 检查参数, 其中第二个参数是需要翻译的单词 */if(argc < 2) {printf("[%s][word]\n", argv[0]);exit(EXIT_FAILURE);}/* 打印环境变量的值 */printf("服务器的主机IP是%s, 端口号是%s\n", host, port);int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd < 0)ErrExit("socket");/* 设置通信结构体 */struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons( atoi(port) );if( inet_aton( host, &addr.sin_addr) == 0) {printf("[%s:%d] Invalid address\n", __FUNCTION__, __LINE__);exit(EXIT_FAILURE);}/* 发起连接请求,注意UDP连接没有三次握手, 不存在连接失败, 只是确定接受端而已 */if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) )ErrExit("connect");/* 执行客户端处理程序 */udp_main(fd, argv[1]);/* 关闭套接字 */close(fd);return 0;
}

udp_main.c

#include "udp.h"/* 其他必要的环境已封装好了,只需要实现与客户端的交互即可* 这里的fd是服务端的socket,* addr是服务端的地址*/
extern void udp_main(const int fd, const char *argv) {char buf[BUFSIZ] = {};send(fd, argv, strlen(argv) + 1, 0);recv(fd, buf, BUFSIZ, 0);printf("buf=%s\n", buf);
}

编译

执行gcc *.c -o test -Wall -lsqlite3 -I ../head/, 得到test的可执行文件;
然后分别运行两边的test文件:
在这里插入图片描述

得到类似这样的结果表示,代码没有问题,可以得到想要的结果
至此就实现了基本功能,接下来再实现其它附加的功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/868515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SCI三区|儿童学习优化算法KLO:基于社会进化和认知学习的优化算法

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;ST Javed受到社会环境下家庭儿童的早期社会学习行为启发&#xff0c;提出了儿童学习优化算法&#xff08;Kids Learning Optimizer, KLO&#xff09;。 2.算法原理 2.…

珍藏多年的计算机内核结构大全笔记,掌握计算机工作原理真不难

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

江洲的《家书》,岂止抵万金

题记 今晨6点钟&#xff0c;像往日一样的背上鱼具包&#xff0c;欲驾乘清凉舒适的晨风&#xff0c;前往味江河堤享受钓翁乐趣。孰料开门一看&#xff0c;朦胧的天空竟下着淅淅沥沥的小雨。 今年的天气异常&#xff0c;是笔者寄居“西川第一天”古镇5年来所未见&#xff1a;再…

顺序表实现

size属于结构体的作用域 如果要访问一个结构体的指针用-> 如果要访问一个结构体的变量用. 点操作 #include<stdio.h> #include<stdlib.h> #include<string.h> #include"seqlist.h" //typedef struct seqList{ // SLDataType* _data; //需…

CSS技巧 - 一日一例 (1):会讨好的热情按钮

题外话: 从今天开始,我准备开设一个新的专栏,专门写 使用CSS实现各种酷炫按钮的方法,本专栏目前准备写40篇左右,大概会完成如下按钮效果: 今天,我来介绍第一个按钮的实现方法:会讨好的热情按钮。为什么我给它起这样的名字呢?你看它像不像一个不停摇尾巴的小黄?当你鼠…

29 H3C SecPath F1000 系统(概述)

29 H3C SecPath F1000 系统 系统全局功能&#xff08;高可靠性 日志设置 报表设置 会话设置 升级中心 Lcense配置 高级虚拟化 管理员 维护 诊断中心 配置指导&#xff09; 高可靠性 1 vrrp VRRP将局域网内的可以承担网关功能的一组设备划分在一起&#xff0c;组成一个备份组…

【Spring Boot】Spring AOP动态代理,以及静态代理

目录 Spring AOP代理一. 代理的概念二. 静态代理三. JDK代理3.1 重写 invoke 方法进⾏功能增强3.2 通过Proxy类随机生成代理对象 四. CGLIB代理4.1 自定义类来重写intercept方法4.2 通过Enhancer类的create方法来创建代理类 五. AOP源码剖析 总结(重中之重&#xff0c;精华) Sp…

git使用总结

git介绍 Git是一款免费、开源的分布式版本控制系统 &#xff0c;用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 git安装 下载地址 # 推荐使用国内镜像下载 http://npm.taobao.org/mirro…

解决win10报“无法加载文件……profile.ps1,因为在此系统上禁止运行脚本”的问题

打开命令行报错 解决方法 使用管理员权限打开PowerShell&#xff1a;WinX, 选择“Windows PowerShell&#xff08;管理员&#xff09;” 输入&#xff1a;Set-ExecutionPolicy -ExecutionPolicy RemoteSigned 输入&#xff1a;y确认修改安全策略 &#xff1a;y确认修改安全策略…

前端学习(三)CSS介绍及选择符

##最近在忙期末考试&#xff0c;因此前端笔记的梳理并未及时更新。在学习语言过程中&#xff0c;笔记的梳理对于知识的加深very vital.因此坚持在明天学习新知识前将笔记梳理完整。 主要内容&#xff1a;CSS介绍及选择符 最后更新时间&#xff1a;2024/7/4 目录 内容&#x…

强化学习的数学原理:值函数近似

在上次课介绍了 TD Learning&#xff0c;实际上这次课依然是介绍 TD &#xff0c;但是上次是用的表格形式介绍的&#xff0c;这次课我们将会介绍基于函数的方式。 算法其实不太难&#xff0c;难的是思路和想法&#xff0c;另外这一节将引入神经网络。 另外最经典的 Deep Q-le…

AutoDL部署半自动大模型标注工具踩坑实录

效果演示 克隆代码 git clone http://github.com/yoletPig/Annotation-with-SAM.git安装SAM cd segment-anything pip install -e .安装SAM-Tool依赖包 pip install -r requirements.txt下载权重 wget https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_

论文新思路!双通道卷积神经网络!最新成果准确率近100%

双通道CNN是一种创新的卷积神经网络架构&#xff0c;它能捕捉到比单通道CNN更丰富的信息&#xff0c;从而提高模型的性能和鲁棒性。 具体点讲&#xff0c;传统CNN采用单个卷积层提取特征&#xff0c;形成特征映射&#xff1b;而双通道CNN则通过两个并行卷积层同时处理输入数据…

越来越多用户和商家选择小程序商城的原因是什么?小程序商城怎么搭建?

得益于小程序的便捷性&#xff0c;越来越多的用户选择在小程序商城购物&#xff0c;越来越多的商家也开始搭建自己的小程序商城。背后原因是什么呢&#xff1f;小程序商城怎么搭建&#xff1f; 用户为何青睐小程序商城&#xff1f; 1、便捷性 小程序商城无需下载安装&#xff…

数据结构——二叉树之c语言实现堆与堆排序

目录 前言&#xff1a; 1.二叉树的概念及结构 1.1 特殊的二叉树 1.2 二叉树的存储结构 1.顺序存储 2.链式存储 2. 二叉树的顺序结构及实现 2.1 堆的概念 ​编辑 2.2 堆的创建 3.堆的实现 3.1 堆的初始化和销毁 初始化&#xff1a; 销毁&#xff1a; 插入&…

开源屏幕分享项目:轻量好用无延迟!!【送源码】

想必大家在日常的工作中&#xff0c;会经常需要分享代码、演示项目或者进行在线教学&#xff0c;这就需要一个既高效又便捷的屏幕共享工具。然而&#xff0c;现有的一些解决方案往往存在延迟高、画质差等问题。 今天就分享一个开源的屏幕共享项目 - screego&#xff0c;不但免…

PHP灵活用工任务小灵通微信小程序系统源码

&#x1f4bc;灵活赚钱新风尚&#xff01;灵活用工任务小灵通微信小程序&#xff0c;兼职自由两不误&#x1f680; &#x1f50d; 一、海量任务&#xff0c;随时随地接单赚外快 还在为找不到合适的兼职而烦恼吗&#xff1f;&#x1f914; 灵活用工任务小灵通微信小程序&#…

Java-Sql注入以及如何解决

sql脚本注入: 如果sql语句使用字符串拼接&#xff0c;可能会出现字符串的拼接&#xff0c;导致sql注入。 #是会先进行预编译&#xff0c;传进来的参数通过占位符填入到已经完成编译的语句中去。

paddleocr运行报错?谈谈解决思路。

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

代码随想录算法训练营第四十七天|1143.最长公共子序列、 1035.不相交的线、53. 最大子序和、392.判断子序列

1143.最长公共子序列 题目链接&#xff1a;1143.最长公共子序列 文档讲解&#xff1a;代码随想录 状态&#xff1a;一开始没想明白为啥要 max(dp[i - 1][j], dp[i][j - 1]) 思路&#xff1a; 如果text1[i - 1] 与 text2[j - 1]相同&#xff0c;那么找到了一个公共元素&#xff…