【在线词典】项目实现

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,一经查实,立即删除!

相关文章

# 深入解析C/C++中的关键运算符:i++, ++i, a=i++, a=++i 及复杂表达式的运算顺序

原因 有没有人跟我一样&#xff0c;根本记不住那么多的运算符优先级,凭感觉猜的运算 顺序&#xff0c;导致代码出错&#xff0c;调试半天&#xff0c;最后发现是优先级的问题有没有跟我一样&#xff0c;看到复杂表达式就头大看到一些复杂的表达式&#xff0c;不知道怎么去分析…

java canonicalName 什么意思

在 Java 中&#xff0c;canonicalName 通常指的是类的规范名称&#xff08;Canonical Name&#xff09;。这是由 Java 提供的一个方法&#xff0c;用于获取类的完整名称&#xff08;包括包名&#xff09;。规范名称是一种标准化的表示方法&#xff0c;与类的全名相同&#xff0…

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; //需…

redis命令的底层执行流程

在 Redis 中&#xff0c;客户端请求命令执行完成后&#xff0c;确实会生成一个响应&#xff0c;但这个响应并不是总是立即发送给客户端的。这是因为 Redis 的单线程模型和 I/O 多路复用机制。以下是 Redis 处理响应数据的一般流程&#xff1a; 命令执行&#xff1a; 客户端发送…

day15补卡

前两题思路和解答一致 404.左叶子之和 &#xff08;优先掌握递归&#xff09; 我的代码思路是传入子节点状态&#xff0c;左节点还是有节点&#xff0c;如果是叶子并为左节点则加入&#xff0c;题解则是通过当前节点去判断左子节点是不是叶子节点&#xff0c;再依此遍历全树&am…

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

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

Java rapidocr

基于PaddleOCR&#xff0c;但是官方并未提供Java版本&#xff0c;而RapidOcr解决了这个问题&#xff0c;不想了解OCR相关知识&#xff0c;开箱即用、不想额外再部署OCR服务&#xff0c;可以直接使用&#xff0c;识别效果也不错&#xff0c;但是发现CPU占用非常高&#xff0c;直…

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…

建立共享linux第三方软件仓库

1. 选择httpd共享方式并下载 [rootserver100 software]# dnf install httpd -y2. 启动httpd&#xff0c;检查防火墙&#xff0c;和selinux是否关闭 [rootserver100 software]# systemctl enable --now httpd[rootserver100 software]# systemctl status firewalld.service ○…

nginx反向代理(多系统)

1. 版本&#xff1a;nginx-1.24.0 &#xff0c;windows 10 64bit&#xff0c;22H2 19045.4529 2. 需求&#xff1a;使用一个nginx反向代理多个系统的内网服务&#xff0c;例如有两个系统&#xff0c;分别为sys1,sys2&#xff0c;物理机的ip分别为192.168.10.125以及192.168.10…

C++ 入门01:初识 C++

一、前言&#xff1a; C作为一种兼具高性能与灵活性的编程语言&#xff0c;其强大的面向对象特性和广泛的应用领域&#xff08;如系统级编程、游戏开发、科学计算等&#xff09;使其成为世界上最受欢迎的语言之一。在本系列文章中&#xff0c;我将详细记录我学习C的基础知识点…

解决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…

NTP权威时间源地址参考

概述 NTP 是 Network Time Protocol 的简称&#xff0c;也就是网络时间协议&#xff0c;它可以通过网络来同步时间的服务器。Windows 自带的 NTP 服务器都在美国&#xff0c;有时间经常无法访问。 中国境内 中国 NTP 快速授时服务 cn.ntp.org.cn阿里云公共 NTP 服务器 ntp…