1.介绍
这是一个没有图形界面的电子词典,以下是实现的功能
1.服务器多线程同时连接多个客户端
2.用户注册
3.用户登录
4.查询单词
5.收藏单词
6.查询当前用户的历史搜索记录
7.查询当前用户的收藏记录
8.退出电子辞典
记得创建以下三个数据表
表格结构如下
哦对,词典的话网上找个txt文档就好了
附上服务器端与客户端代码
2.服务器端代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>
#define MAX_CLIENTS 10
#define MAX_WORD_SIZE 100
#define MAX_DEFINITION_SIZE 512
void *handle_client(void *arg);
int clients[MAX_CLIENTS];
int client_count = 0;
char definition[MAX_DEFINITION_SIZE];
sqlite3* mydb = NULL;
char user_id[20];//登陆了的账户密码
char user_pwd[16];
int falg;
/**
* 功能:接收注册的账号密码
*/
void recv_register(int newSocket)
{
char** resultp;
int row;
int column;
char id[20];//注册时的账户密码
char password[16];
//接收账号
memset(id,0,sizeof(id));
recv(newSocket,id, sizeof(id), 0);
//接收密码
memset(password,0,sizeof(password));
recv(newSocket,password, sizeof(password), 0);
//检测账号是否重复
char regbuffer[256] = "select * from dict_user;";
sqlite3_get_table(mydb,regbuffer,&resultp,&row,&column,NULL);
memset(regbuffer,0,sizeof(regbuffer));
for(int i=0;i<(row+1)*column;i++){
if(strcmp(id,resultp[i])==0){//账号重复
char a[6] = "-1";
send(newSocket,a,strlen(a),0);
return;
}
}
memset(regbuffer,0,256);
snprintf(regbuffer,256,"insert into dict_user(id,password)values('%s','%s');",id,password);
if(strlen(id)<16 && strlen(regbuffer) <7)
{
char b[6] = "-2";
send(newSocket,b,strlen(b), 0);
return ;
}
sqlite3_get_table(mydb,regbuffer,&resultp,&row,&column,NULL);
char c[6] = "1";
send(newSocket,c,strlen(c), 0);
memset(regbuffer,0,sizeof(regbuffer));
}
/**
* 功能:登录
*/
void recv_user_log(int newSocket)
{
char** resultp;
int row;
int column;
int id_count=0;//用于判断用户名是否正确
int pwd_count = 0;//密码
//接收账号
memset(user_id,0,sizeof(user_id));
recv(newSocket,user_id, sizeof(user_id), 0);
//接收账号
memset(user_pwd,0,sizeof(user_pwd));
recv(newSocket,user_pwd, sizeof(user_pwd), 0);
//检测账号是否存在
char regbuffer[256];
snprintf(regbuffer,sizeof(regbuffer),"select * from dict_user where id='%s' and password='%s';",user_id,user_pwd);
sqlite3_get_table(mydb,regbuffer,&resultp,&row,&column,NULL);
memset(regbuffer,0,sizeof(regbuffer));
for(int i=0;i<(row+1)*column;i++){
if(strcmp(user_id,resultp[i])==0){//账号存在
id_count += 1;
}
if(strcmp(user_pwd,resultp[i])==0)//密码正确
{
pwd_count += 1;
}
}
if(id_count == 1 && pwd_count == 1)
{
char a[6] = "1";
send(newSocket,a,strlen(a),0);
return;
}
if(id_count != 1)
{
char b[6] = "-1";
send(newSocket,b,strlen(b), 0);
return ;
}
if(id_count != 1 && pwd_count != 1)
{
char c[6] = "-2";
send(newSocket,c,strlen(c), 0);
}
memset(regbuffer,0,sizeof(regbuffer));
}
/**
* 功能;收藏单词
*/
void searchWord(const char *filename,char *targetWord,int newSocket) {
char** resultp;
int row;
int column;
char buffer[1024];
char input[6];//是否收藏
FILE *file = fopen(filename, "r");
if (file == NULL) {
perror("Error opening file");
return;
}
char currentWord[MAX_WORD_SIZE];
memset(buffer,0,sizeof(buffer));
memset(currentWord,0,sizeof(currentWord));
memset(definition,0,sizeof(definition));
while (fscanf(file, "%s %[^\n]", currentWord, definition) == 2) {
if (strcmp(currentWord, targetWord) == 0) {
recv(newSocket, input, sizeof(input), 0);
if(strcmp(input,"yes") == 0)
{
snprintf(buffer,sizeof(buffer),"insert into collect(id,word,definition)values('%s','%s','%s');",user_id,currentWord,definition);
sqlite3_get_table(mydb,buffer,&resultp,&row,&column,NULL);
memset(buffer,0,sizeof(buffer));
}
send(newSocket,definition,strlen(definition),0);
snprintf(buffer,sizeof(buffer),"insert into record(id,word,definition)values('%s','%s','%s');",user_id,currentWord,definition);
sqlite3_get_table(mydb,buffer,&resultp,&row,&column,NULL);
printf("单词:%s\n解释:%s\n", currentWord, definition);
fclose(file);
memset(targetWord,0,sizeof(targetWord));
return; // 找到了,可以选择退出循环或函数
}
}
memset(targetWord,0,sizeof(targetWord));
send(newSocket, "1",2, 0);//传输单词
printf("单词 \"%s\" 未在字典中找到。\n", targetWord);
fclose(file);
}
/**
* 功能查询历史记录并返回
*/
void select_reword(int newSocket)
{
char** resultp;
int row;
int column;
char buffer[124];
char buffer1[4096];
memset(buffer1,0,sizeof(buffer1));
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"select * from record where id = '%s'",user_id);
sqlite3_get_table(mydb,buffer,&resultp,&row,&column,NULL);
for(int i=0;i<(row+1)*column;i++)
{
strcat(buffer1, resultp[i]);//拼接字符串
strcat(buffer1, "\t\t"); // 使用制表符分隔
if((i+1)%column == 0)//这里是换行,每当下标i取模列为0的时候换行
{
strcat(buffer1, "\n");//换行
}
}
send(newSocket,buffer1,sizeof(buffer1), 0);//传输单词
}
/**
* 功能:查询收藏记录并返回
*/
void collect_word(int newSocket)
{
char** resultp;
int row;
int column;
char buffer[124];
char buffer1[4096];
memset(buffer1,0,sizeof(buffer1));
memset(buffer,0,sizeof(buffer));
snprintf(buffer,sizeof(buffer),"select * from collect where id = '%s'",user_id);
sqlite3_get_table(mydb,buffer,&resultp,&row,&column,NULL);
for(int i=0;i<(row+1)*column;i++)
{
strcat(buffer1, resultp[i]);//拼接字符串
strcat(buffer1, "\t\t"); // 使用制表符分隔
if((i+1)%column == 0)//这里是换行,每当下标i取模列为0的时候换行
{
strcat(buffer1, "\n");//换行
}
}
send(newSocket,buffer1,sizeof(buffer1), 0);//传输单词
}
int main(int argc, char **argv) {
//打开数据库文件
int ret = sqlite3_open("./dict_select.db", &mydb);
if(ret != 0)
{
perror("opendb failed");
return -1;
}
int serverSocket, newSocket;
struct sockaddr_in serverAddr, newAddr;
socklen_t addr_size;
// 创建服务器套接字
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket < 0) {
perror("服务器套接字创建失败");
exit(1);
}
printf("服务器套接字创建成功\n");
serverAddr.sin_family = AF_INET;
serverAddr.sin_port =htons(12345);//htons(atoi(argv[2]))
serverAddr.sin_addr.s_addr = inet_addr("192.168.124.138");//INADDR_ANY;//inet_addr(argv[1])
// 绑定服务器套接字
if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
perror("绑定失败");
exit(1);
}
printf("绑定成功\n");
// 监听连接
if (listen(serverSocket, 10) == 0) {
printf("监听中...\n");
} else {
printf("监听失败\n");
}
// 接受客户端连接并创建线程
while (1) {
addr_size = sizeof(newAddr);
newSocket = accept(serverSocket, (struct sockaddr *)&newAddr, &addr_size);
if (client_count < MAX_CLIENTS) {
pthread_t tid;
clients[client_count] = newSocket;
pthread_create(&tid, NULL, handle_client, &newSocket);
client_count++;
} else {
printf("客户端连接达到最大限制,拒绝连接\n");
close(newSocket);
}
}
return 0;
}
void *handle_client(void *arg) {
int newSocket = *((int *)arg);
char buffer[24];
char regbuffer[4];
while (1) {
memset(regbuffer,0,sizeof(regbuffer));
recv(newSocket, regbuffer, sizeof(regbuffer), 0);
falg = atoi(regbuffer);
printf("执行:%d号操作\n",falg);
switch(falg)
{
case 0:
recv_register(newSocket);
break;
case 1:
recv_user_log(newSocket);
break;
case 2:
recv(newSocket, buffer, sizeof(buffer), 0);
searchWord("dict.txt",buffer,newSocket);
break;
case 3:
collect_word(newSocket);
break;
case 4:
select_reword(newSocket);
break;
}
if(falg == 5)
{
break;
}
}
}
3.客户端代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/time.h>
int clientSocket;
struct sockaddr_in serverAddr;
char buffer[2048];
/**
* 功能:登录注册菜单
*/
void menu(void)
{
printf("*********************************************\n");
printf("* 0.注册 *\n");
printf("* 1.登录 *\n");
printf("*********************************************\n");
printf("*********************************************\n");
}
void menu2(void)
{
printf("*********************************************\n");
printf("2.查询单词释义 \n");
printf("3.查询收藏单词 \n");
printf("4.查询搜索记录 \n");
printf("5.退出 \n");
printf("*********************************************\n");
}
/**
* 功能:用户注册
*/
void user_register(void)
{
char id[20];
char password[16];
char regbuffer[20];
memset(regbuffer,0,20);
memset(id,0,sizeof(id));
printf("请输入用户名:");
scanf("%s",id);
//发送账号
send(clientSocket,id,strlen(id), 0);
memset(password,0,sizeof(password));
printf("请输入密码:");
scanf("%s",password);
//发送密码
send(clientSocket, password, strlen(password), 0);
recv(clientSocket, regbuffer, sizeof(regbuffer), 0);
if(strcmp(regbuffer,"1") == 0)
{
printf("注册成功!\n");
}
if(strcmp(regbuffer,"-1") == 0)
{
printf("注册失败,账户重复!\n");
}
if(strcmp(regbuffer,"-2") == 0)
{
printf("账户或密码长度不正确。请输入16位以下账户和7位以下密码\n");
}
}
/**
* 功能:用户登录
*
*/
int user_log(void)
{
char id[20];
char password[16];
char regbuffer[20];
memset(regbuffer,0,20);
memset(id,0,sizeof(id));
printf("请输入用户名:");
scanf("%s",id);
//发送账号
send(clientSocket,id,strlen(id), 0);
memset(password,0,sizeof(password));
printf("请输入密码:");
scanf("%s",password);
//发送密码
send(clientSocket, password, strlen(password), 0);
recv(clientSocket, regbuffer, sizeof(regbuffer), 0);
if(strcmp(regbuffer,"1") == 0)
{
printf("登录成功!\n");
return 1;
}
if(strcmp(regbuffer,"-1") == 0)
{
printf("登录失败,用户名不存在!\n");
}
if(strcmp(regbuffer,"-2") == 0)
{
printf("登录失败,用户名或密码错误\n");
}
}
/**
* 功能:查询单词
*/
void select_word(void)
{
char buffer[24],definition[1024],input[6];
printf("请输入你要查询的单词:");
memset(buffer,0,sizeof(buffer));
scanf("%s",buffer);
send(clientSocket, buffer, strlen(buffer), 0);//传输单词
printf("是否收藏该代词(yes/no):");
scanf("%s",input);
if(strcmp(input,"yes") == 0)
{
send(clientSocket, input, strlen(input), 0);
printf("收藏成功!\n");
}else
{
printf("收藏失败!");
}
memset(definition,0,sizeof(definition));
int word_count = recv(clientSocket,definition, sizeof(definition), 0);
if(strlen(definition) > 2)
{
printf("单词为:%s\n",buffer);
printf("释义为:%s\n",definition);
}
else
{
printf("单词不存在\n");
}
}
/**
* 功能:历史记录
*/
void select_reword(void)
{
char buffer[4096];
memset(buffer,0,sizeof(buffer));
recv(clientSocket, buffer, sizeof(buffer), 0);
printf("%s",buffer);
}
/**
* 功能:收藏记录
*/
void collect_word(void)
{
char buffer[4096];
memset(buffer,0,sizeof(buffer));
recv(clientSocket, buffer, sizeof(buffer), 0);
printf("%s",buffer);
}
int dict_sekect_menu(void)
{
char falg[5];
while(1)
{
menu2();
printf("请输入您要执行的操作:");
scanf("%s",falg);
switch(atoi(falg))
{
case 2:
send(clientSocket, falg, strlen(falg), 0);
select_word();
break;
case 3:
send(clientSocket, falg, strlen(falg), 0);
collect_word();
break;
case 4:
send(clientSocket, falg, strlen(falg), 0);
select_reword();
break;
case 5:
break;
default:
printf("输入有误,请选择合法输入\n");
}
if(atoi(falg) == 5)
{
return 0;
}
}
}
int main(int argc,char** argv) {
int exit1;
char cfalg[5];
// 创建客户端套接字
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket < 0) {
perror("套接字创建失败");
exit(1);
}
printf("客户端套接字创建成功\n");
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(12345);
serverAddr.sin_addr.s_addr = inet_addr("192.168.124.138");
// 连接到服务器
if (connect(clientSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
perror("连接失败");
exit(1);
}
printf("连接成功\n");
while (1) {
memset(cfalg,0,sizeof(cfalg));
//登录与注册界面
menu();
printf("请输入您要执行的操作:");
scanf("%s",cfalg);
//登录和注册
switch(atoi(cfalg))
{
//注册
case 0:
send(clientSocket, cfalg, strlen(cfalg), 0);
user_register();
break;
//登录账号
case 1:
send(clientSocket, cfalg, strlen(cfalg), 0);
int ret = user_log();
if(ret == 1)
{
exit1 = dict_sekect_menu();
}
break;
case 5:
break;
default:
printf("输入错误,请输入合法选项\n");
}
if(exit1 == 0)
{
send(clientSocket, "5", strlen("5"), 0);
printf("退出成功!\n");
break;
}
}
return 0;
}