目录

项目要求:

代码

服务器代码

客户端

运行截图

注册

首次注册

重复注册

数据库

登录

正常登录

重复登录

数据库

查询

数据库

查询历史

退出

数据库

​编辑


项目要求:

  1. 登录注册功能,不能重复登录,重复注册

  2. 单词查询功能

  3. 历史记录功能,存储单词,意思,以及查询时间

  4. 基于TCP,支持多客户端连接

  5. 采用数据库保存用户信息与历史记录

  6. 将dict.txt的数据导入到数据库中保存。

  7. 按下ctrl+c退出客户端后,注销该客户端的登录信息

格式要求:

  1. main函数只跑逻辑,不允许跑功能代码

  2. 功能代码封装成函数

代码

服务器代码

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include <sqlite3.h>
#include<time.h>
//打印错误信息的宏函数
#define ERR_MSG(msg) do{\fprintf(stderr," __%d__",__LINE__);\perror(msg);\
}while(0);#define PORT 8888             //1024~49151端口号
#define IP "192.168.31.31"   //本机IP,用ifcongfig查看//定义协议
#define R 1  //注册
#define L 2  //登录
#define O 3  //注销退出
#define M 4  //修改
#define Q 5  //查询
#define H 6  //历史记录typedef struct
{int type;   //存储协议char name[128];char data[128];int flag;  //判断是否登录
}MSG;int do_register(int newfd,MSG *msg,sqlite3 *db);
int do_login(int newfd,MSG *msg,sqlite3 *db);
int do_query(int newfd,MSG *msg,sqlite3 *db);
int do_history(int newfd,MSG *msg,sqlite3 *db);
int do_logout(int newfd,MSG *msg,sqlite3 *db);
int do_clint(int newfd,sqlite3 *db)
{MSG msg;memset(&msg,0,sizeof(msg));//服务器接收客户端信息,通过规定协议判断客户端请求while (recv(newfd,&msg,sizeof(MSG),0)>0)//while (1){//recv(newfd,&msg,sizeof(msg),0);printf("type %d\n",msg.type);printf("name %s\n",msg.name);printf("data %s\n",msg.data);//根据结构体中的协议号调用程序响应处理switch(msg.type){case R:do_register(newfd,&msg,db);break;case L:do_login(newfd,&msg,db);break;case Q:do_query(newfd,&msg,db);break;case H:do_history(newfd,&msg,db);break;case O:do_logout(newfd,&msg,db);break;default:         printf("GGGGGGGGG\n");break;}}char sql[128];sprintf(sql,"delete from msg where name='%s';",msg.name);//printf("%s\n",sql);char* errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}else{printf("用户注销>>>>X_X\n");strcpy(msg.data,"退出成功~");}printf("客户端退出...............\n");close(newfd);exit(0);
}int do_register(int newfd,MSG *msg,sqlite3 *db)//注册函数
{char * errmsg;char sql[300];//查重int nrow, ncloumn;                         //数据库行数和列数char **resultp;                            //定义二级指针保存SOL语句执行的结果//拼接SOL语句,查询用户名和密码与数据库内容是否匹配sprintf(sql, "select * from msg where name='%s';", msg->name);//printf("%s\n", sql); //调试语句if (sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg)!=SQLITE_OK){printf("%s\n",errmsg);return -1;}//printf("%d\n",nrow);if(nrow==1){strcpy(msg->data,"重复注册!!!");send(newfd,msg,sizeof(*msg),0);return 1;}else{//printf("%s\n",sql);//printf("%s\n",msg->data);//printf("flag=%d\n",msg->flag);//向数据库中插入信息,flag为0,表示未登录sprintf(sql,"insert into msg values('%s',\'%s\',%d);",msg->name,msg->data,msg->flag);//printf("%s\n",sql);char* errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}//printf("insert success\n");//strcpy(msg->data,"插入成功");else{strcpy(msg->data,"注册成功");}if (send(newfd,msg,sizeof(*msg),0)<0){ERR_MSG("send");return -1;}}
}int do_login(int newfd,MSG *msg,sqlite3 *db)//登录处理函数
{char * errmsg;char sql[300];//查重//char *errmsg;int nrow, ncloumn;                         //数据库行数和列数char **resultp;                            //定义二级指针保存SOL语句执行的结果//拼接SOL语句,查询用户名和密码与数据库内容是否匹配sprintf(sql, "select * from msg where name='%s' and passwd='%s';", msg->name,msg->data);//printf("%s\n", sql); //调试语句if (sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg)!=SQLITE_OK){printf("%s\n",errmsg);return -1;}if(nrow==1){//if(resultp[5]==1)if(strcmp(resultp[5],"1")==0)//flag=1表示用户已登录 返回信息给客户端{strcpy(msg->data,"该用户已登录,洗洗睡吧");send(newfd,msg,sizeof(*msg),0);return -1;}bzero(sql,sizeof(sql));msg->flag=1;sprintf(sql,"update msg set flag=%d where name='%s' and passwd='%s';",msg->flag,msg->name,msg->data);//printf("%s\n",sql);if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}strcpy(msg->data,"OK");send(newfd,msg,sizeof(*msg),0);return 1;}else{strcpy(msg->data,"!!!账号密码有误!!!");send(newfd,msg,sizeof(MSG),0);}return 0;}int do_query(int newfd,MSG *msg,sqlite3 *db)//查询单词
{char tm[128];char * errmsg;char sql[300];//查重//char *errmsg;int nrow, ncloumn;                         //数据库行数和列数char **resultp;                            //定义二级指针保存SOL语句执行的结果//拼接SOL语句,查询用户名和密码与数据库内容是否匹配sprintf(sql, "select * from dict where word='%s';", msg->data);//printf("%s\n", sql); //调试语句if (sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg)!=SQLITE_OK){printf("%s\n",errmsg);return -1;}//printf("%d\n",nrow);if(nrow==1){time_t t;struct tm *info = NULL;t = time(NULL);info = localtime(&t);//\r转义字符,将光标重新移动回开头sprintf(tm,"%d-%02d-%02d %02d:%02d:%02d\r", \info->tm_year+1900, info->tm_mon+1, info->tm_mday,\info->tm_hour, info->tm_min, info->tm_sec);//strcpy(tm,asctime(t));//printf("%s\n",tm);//printf("zhongwen  %s\n",resultp[3]);sprintf(sql,"insert into history values('%s',\'%s\','%s');",msg->name,tm,msg->data);//printf("%s\n",sql);char* errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}strcpy(msg->data,resultp[3]);send(newfd,msg,sizeof(*msg),0);return 1;}else{strcpy(msg->data,"NO");send(newfd,msg,sizeof(MSG),0);}return 0;
}
int do_history(int newfd,MSG *msg,sqlite3 *db)//历史记录查询
{printf("test history\n");//char his[256];//拼接历史记录char * errmsg;char sql[300];//查重//char *errmsg;int nrow, ncloumn;                         //数据库行数和列数char **resultp;                            //定义二级指针保存SOL语句执行的结果//拼接SOL语句,查询用户名和密码与数据库内容是否匹配//sprintf(sql, "select * from history;");strcpy(sql,"select * from history;");//printf("%s\n", sql); //调试语句if (sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg)!=SQLITE_OK){printf("%s\n",errmsg);return -1;}if(nrow!=0){//printf("query successful.\n");//printf("test hang:%d  lie:%d\n",nrow,ncloumn);int i=0;for (i=3; i<(nrow+1)*ncloumn; i+=3){bzero(msg->data,sizeof(msg->data));/*  printf("ceshi %s\n",msg->data);printf("%s\n",resultp[i]);printf("%s\n",resultp[i+1]);printf("%s\n",resultp[i+2]);*/sprintf(msg->data,"%s %s %s",resultp[i],resultp[i+2],resultp[i+1]);//拼接记录信息写入结构体printf("%s\n",msg->data);if(send(newfd,msg,sizeof(*msg),0)<0){ERR_MSG("send");return -1;}bzero(msg->data,sizeof(msg->data));}msg->data[0]='\0';if(send(newfd,msg,sizeof(MSG),0)<0){ERR_MSG("send");return -1;}return 1;}elsereturn 0;}
int do_logout(int newfd,MSG* msg,sqlite3 *db)//注销函数
{char sql[128];sprintf(sql,"delete from msg where name='%s';",msg->name);//从数据库中删除用户信息printf("%s\n",sql);char* errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}else{printf("用户已注销,客户端GG。X_X\n");strcpy(msg->data,"退出成功~");}if(send(newfd,msg,sizeof(MSG),0)<0){ERR_MSG("send");return -1;}}
int main(int argc, const char *argv[])
{//创建流式套接字int sfd=socket(AF_INET,SOCK_STREAM,0);if (sfd < 0){ERR_MSG("socket");return -1;}printf("create socket success\n");//允许端口快速复用int reuse=1;if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){ERR_MSG("setsockopt");return -1;}//填充地址信息结构体,真实地址信息结构体与协议族相关//AF_INET,所以详情看》man 7 ipstruct sockaddr_in sin;sin.sin_family           =AF_INET;sin.sin_port             =htons(PORT);                 //网络字节序sin.sin_addr.s_addr      =inet_addr(IP);                //网络字节序的IP地址//将地址信息结构体绑定到套接字上if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n");//将套接字设置为被动监听状态,让内核去监听是否有客户端链接if (listen(sfd,10)<0){ERR_MSG("listen");return -1;}printf("listen success\n");//打开数据库sqlite3* db = NULL;if(sqlite3_open("./dict.db", &db) != SQLITE_OK){printf("err_code:%d\n", sqlite3_errcode(db));printf("errmsg:%s\n", sqlite3_errmsg(db));fprintf(stderr, "__%d__ sqlite3_open failed\n", __LINE__);return -1;}printf("sqlite3_open:dict.db success\n");//创建信息表char* sql = "create table if not exists msg ( name char, passwd char,flag int);" ;char* errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}printf("create table msg success\n");//创建历史记录表char* sql2 = "create table if not exists history (name char, datatime char, word char);" ;
//char* errmsg2 = NULL;if(sqlite3_exec(db, sql2, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);return -1;}printf("create table success\n");    struct sockaddr_in cin;socklen_t addrlen= sizeof(cin);//从已完成的队列头中,取出一个客户端的信息,创建生成一个新的套接字文件描述符//该文件描述符才是与客户端通信的文件描述符!!!!
/*  int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);if (newfd<0){perror("accept");return -1;}*///网络字节序的IP--->点分十进制 网络字节序port转换成主机字节序///printf("[%s : %d] newfd = %d \n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);printf("***************************等待客户端链接*****************************\n");while (1){int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);if (newfd<0){perror("accept");return -1;}
printf("[%s : %d] newfd = %d \n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);pid_t pid=fork();if (pid<0){ERR_MSG("fork");exit(-1);}else if(pid==0)//子进程{//处理客户端请求close(sfd);do_clint(newfd,db);}else{//父进程close(newfd);}close(newfd);}close(sfd);
//  close(newfd);return 0;
}

客户端

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define ERR_MSG(msg) do{\fprintf(stderr," __%d__",__LINE__);\perror(msg);\
}while(0);#define PORT 8888             //1024~49151端口号
#define IP "192.168.31.31"   //本机IP,用ifcongfig查看
typedef struct
{int type;   //存储协议char name[128];char data[128];int flag;  //判断是否登录
}MSG;//定义协议
#define R 1  //注册
#define L 2  //登录
#define O 3  //注销退出
#define Q 5  //查询
#define H 6  //历史记录//注册函数
int do_register(int sfd,MSG *msg)
{//printf("%ld\n",sizeof(*msg));msg->type=R;msg->flag=0;printf("请输入账号>>>");//账号输入scanf("%s",msg->name);getchar();printf("请输入密码>>>");//密码输入scanf("%s",msg->data);getchar();//printf("ceshi %s\n",msg->name);//printf("ceshi %s\n",msg->data);//memcpy(send_buf,&msg,sizeof(msg));//客户端先发送if (send(sfd,msg,sizeof(*msg),0)<0)//if (send(sfd,send_buf,sizeof(send_buf),0)<0){ERR_MSG("send");return -1;}//memset(&msg,0,sizeof(msg));//后接收if (recv(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("recv");return -1;}printf("%s\n",msg->data);return 0;
}//登录函数
int do_login(int sfd,MSG *msg)
{msg->type=L;printf("请输入账号>>>");//账号输入scanf("%s",msg->name);getchar();printf("请输入密码>>>");//密码输入scanf("%s",msg->data);getchar();//客户端先发送if (send(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("send");return -1;}//后接收if (recv(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("recv");return -1;}//if(strncmp(msg->data,"OK",3)==0)if(strcmp(msg->data,"OK")==0){printf("***************登陆成功****************\n\n");//    printf("***************************************\n");return 1;}else{//printf("登录失败\n");printf("%s\n",msg->data);return 0;}return 0;}//退出登录函数
int do_logout(int sfd,MSG *msg)
{if (msg->flag==0){printf("用户未登录\n");return -1;}msg->type=O;//发送退出登录协议printf("%d\n",msg->type);//客户端先发送if (send(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("send");return -1;}//后接收if (recv(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("recv");return -1;}printf("%s\n",msg->data);return 0;
}//查询函数
int do_query(int sfd,MSG *msg)
{msg->type=Q;//输入要查询的单词printf("请输入要查询的单词\n");fgets(msg->data,sizeof(msg->data),stdin);msg->data[strlen(msg->data)-1]='\0';//printf("test %s\n",msg->data);//客户端先发送if (send(sfd,msg,sizeof(MSG),0)<0){ERR_MSG("send");return -1;}//后接收if (recv(sfd,msg,sizeof(*msg),0)<0){ERR_MSG("recv");return -1;}if (strcmp(msg->data,"NO")==0){printf("XXXXXXX未查询到对应单词XXXXXXXXX\n");}else{printf("中文意思为:%s\n",msg->data);}return 0;
}//查询历史记录
int do_history(int sfd,MSG *msg)
{msg->type=H;//printf("test %d\n",msg->type);if (send(sfd,msg,sizeof(MSG),0)<0){printf("发送失败\n");return -1;}while (1){if (recv(sfd,msg,sizeof(MSG),0)<0){ERR_MSG("recv");return -1;}if (msg->data[0]==0){break;}printf("%s\n",msg->data);}return 0;
}int main(int argc, const char *argv[])
{MSG msg;//printf("%ld\n",sizeof(msg));//创建流式套接字int sfd=socket(AF_INET,SOCK_STREAM,0);if (sfd<0){ERR_MSG("socket");return -1;}//绑定客户端的地址信息结构体》非必须填写//填充要连接的服务器的地址信息结构体struct sockaddr_in sin;sin.sin_family     =AF_INET;sin.sin_port       =htons(PORT);sin.sin_addr.s_addr=inet_addr(IP);//链接服务器if (connect(sfd,(struct sockaddr*)&sin,sizeof(sin))<0){ERR_MSG("connect");return -1;}start:   while (1)    //登录交互界面{printf("***************************************\n");printf("****************1:注册*****************\n");printf("****************2:登录*****************\n");printf("****************3:退出*****************\n");printf("***************************************\n");printf("请选择>>>");int n;scanf("%d",&n);getchar();//吸收垃圾字符switch(n){case 1:do_register(sfd,&msg);break;case 2:if(do_login(sfd,&msg)==1)goto next;break;case 3:close(sfd);exit(0);break;default:printf("请输入正确选项!!!\n");}}
next:while (1){printf("***************************************\n");printf("****************1:查询翻译*************\n");printf("****************2:查询历史*************\n");printf("****************3:退出登录*************\n");printf("***************************************\n");printf("请选择>>>");int n;scanf("%d",&n);getchar();//吸收垃圾字符switch(n){case 1:do_query(sfd,&msg);break;case 2:do_history(sfd,&msg);break;case 3:do_logout(sfd,&msg);goto start;break;default:printf("请输入正确选项!!!\n");break;}}close(sfd);return 0;
}

运行截图

注册

首次注册

重复注册

数据库

登录

正常登录

重复登录

数据库

登陆后flag为1

查询

数据库

查询后将信息插入数据库

查询历史

退出

按程序退出或者ctrl+c结束,都将注销用户,从数据库中删除用户信息

数据库

网络编程项目——在线电子词典相关推荐

  1. 基于数据库及TCP网络编程实现的电子词典

    目录 一.前言 二.项目介绍 三.功能实现 3.1. 用户注册 3.1.1 功能演示 3.1.2 功能函数实现 3.2. 用户登录 3.2.1 功能演示 3.2.2 功能函数实现 3.3. 查询单词 ...

  2. 【基于TCP 在线电子词典】

    基于TCP 在线电子词典 项目功能 流程图 客户端 服务器端 功能实现 服务器 客户端 功能演示 注册功能 登录功能 查询单词功能 查询记录 注销登录(返回上级) 不允许重复登录 Ctrl + C注销 ...

  3. 基于 Netty 网络编程项目实战课程

    一 基于 Netty 网络编程项目实战课程 1项目介绍 2Netty 介绍与相关基础知识 2.1Netty 介绍 简介 Netty 是由 JBOSS 提供的一个 java 开源框架.Netty 提供异 ...

  4. 基于Linux的socket网络编程项目——游侠手机商城

    基于Linux的socket网络编程项目--游侠手机商城 一.项目说明 二.项目使用的技术 三.客户端搭建 四.服务器端搭建 一.项目说明 本项目是一个仿真手机商城类系统,基本功能: 登录界面功能:用 ...

  5. python网络编程项目_python网络编程详解

    最近在看<UNIX网络编程 卷1>和<FREEBSD操作系统设计与实现>这两本书,我重点关注了TCP协议相关的内容,结合自己后台开发的经验,写下这篇文章,一方面是为了帮助有需要 ...

  6. Linux操作系统C语言网络编程学生在线考试系统(带完整项目源码)

    目录 一.项目功能 1.用户登录 2.教师登录 3.学生登录 二.需求分析 1.多用户登录,有并发需求. 2.需要数据库存储一堆信息. 三.软硬件开发平台 1.硬件 2.软件 四.技术点 1.使用并发 ...

  7. 网络编程项目(聊天室项目)

    一.实现目标 一个在Linux下可以使用的聊天软件,要求至少实现如下功能: 1. 采用Client/Server架构 2. Client A 登陆聊天服务器前,需要注册自己的ID和密码 3. 注册成功 ...

  8. python网络编程项目_Python网络编程攻略

    第1章套接字.IPv4和简单的客户端/服务器编程 本章攻略: 打印设备名和IPv4地址 获取远程设备的IP地址 将IPv4地址转换成不同的格式 通过指定的端口和协议找到服务名 主机字节序和网络字节序之 ...

  9. C网络编程项目 图书借阅系统(一)

    1.项目名称 图书借阅系统 2.项目需求 对于图书馆中的书籍信息的管理,可以增.删.改.查书籍的信息,完成借阅.归还书籍的要求. 3.项目功能 1.采用并发服务器,可以同时处理多个客户端的请求. 2. ...

  10. Linux网络编程之六 --在线英英字典的实现

    综合项目:在线英英字典 服务器端 head.h: ​ server.c do_client.c Makefile 客户端 head.h client.c Makefile 关注微信公众号获取更多资讯

最新文章

  1. Android Color 判断色值小结
  2. JavaScript学习历程和心得
  3. 金融贷款逾期的模型构建1
  4. make时候说找不到makefile_找不到答案的时候,就去看一看这个世界
  5. ubuntu开启端口_RChain节点运行无门槛教程(二)--Windows-Ubuntu
  6. 【page-monitor 前端自动化 上篇】初步调研
  7. app启动速度阶段指标
  8. unity ppr_智能自动PPR更改事件策略
  9. 维基媒体宣布采用 Vue.js 进行前端开发
  10. 常用的Linux操作命令
  11. Ububtu 18.04 安装 mysql 和 phpmyadmin 过程记录
  12. 2020-07-07
  13. QT高级编程技巧(一)-- 编写高效的signal slot通信代码
  14. UDP与TCP报文格式,字段意义
  15. STP配置 HSRP配置 端口追踪
  16. excel批量改名字(含识别区分)
  17. xss漏洞原因以及如何应对
  18. 51单片机_7-2 使用内部计时器实现时钟显示
  19. 我做了一个艰难的决定
  20. 基于Java的开源3D游戏引擎jMonkeyEngine

热门文章

  1. 将超星图书转成PDF文档
  2. 计算机组成原理第6版课后答案,计算机组成原理第6章习题参考答案
  3. 使用Origin从图片中准确提取数据
  4. wsdl2java maven_maven wsdl2java配置无法正常工作
  5. vbs实现恶搞无限弹窗,复制粘贴就能用
  6. matlab肆,matlab入门教程
  7. ska测试软件怎么用,wow伤害测试软件SIMC怎么用?SIMC使用详细攻略
  8. 发那科机器人点位编辑_分步详解 | 发那科机器人如何进行零点标定
  9. 冰与火之歌:国产操作系统风云录
  10. 尚硅谷大数据项目之Flink实时数仓-踩坑记录和笔记记录