涉及知识
本项目主要涉及了,C语言,IO进线程,网络编程的一些知识。
主要组成部分
客户端
客户端主要的功能是对用户的登录账号和密码进行识别,判断账号和密码是否存在,如果不存在提醒用户账号密码不存在,如果存在则判断账号密码是否匹配,如果账号密码匹配则登陆系统成功,失败则进行提示,当成功进入系统后可执行单词的查询和历史记录的查看操作。
下面是实现上诉功能的代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include "history_data.h"
#include "history_seek.h"
int main(int argc, char *argv[])
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("socket");
return -1;
}
char ip_data[20]={0},port_data[20]={0};
system("clear");
printf("\033[35m 请输入服务器ip地址 \033[0m\n");
gets(ip_data);
printf("\033[35m 请输入服务器端口 \033[0m\n");
gets(port_data);
system("sl");
struct sockaddr_in addr;
addr.sin_family =AF_INET;
addr.sin_port =htons(atoi(port_data));
addr.sin_addr.s_addr =inet_addr(ip_data);
if(-1==connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)))
{
perror("connect");
return -1;
}
while(1)
{
system("clear");
printf("\033[5;35m*************************************************\033[0m\n");
printf("\033[5;35m**\033[0m 1注册 \033[5;35m**\033[0m\n");
printf("\033[5;35m**\033[0m 2登陆 \033[5;35m**\033[0m\n");
printf("\033[5;35m**\033[0m 输入quit结束服务 \033[5;35m**\033[0m\n");
printf("\033[5;35m*************************************************\033[0m\n");
char query_data[128]={0};
scanf("%s",query_data);
sendto(sockfd,query_data,sizeof(query_data),0,NULL,0);
if(strcmp(query_data,"quit")==0)
{
system("clear");
printf("\033[7;31m***************服务已结束,感谢你的使用**********************\033[0m\n");
break;
}
else
{
if(strcmp(query_data,"1")==0)
{
system("clear");
char account_number[32]={0},the_code[32]={0};
printf("\033[5;35m 进入注册系统 \033[0m\n");
printf("\033[35m 输入你的账号(32位以内) \033[0m\n");
scanf("%s",account_number);
sendto(sockfd,account_number,sizeof(account_number),0,NULL,0);
printf("\033[35m 输入你的密码(32位以内) \033[0m\n");
scanf("%s",the_code);
sendto(sockfd,the_code,sizeof(the_code),0,NULL,0);
bzero(query_data,0);
recvfrom(sockfd,query_data,sizeof(query_data),0,NULL,NULL);
printf("%s\n",query_data);
if(strcmp(query_data,"a")==0)
{
printf("\033[5;31m*************注册成功将返回上一级******************\033[0m\n");
sleep(2);
continue;
}
else if(strcmp(query_data,"b")==0)
{
printf("\033[5;31m****************打开数据库失败**********************\033[0m\n");
sleep(2);
continue;
}
else if(strcmp(query_data,"c")==0)
{
printf("\033[5;31m****************打开数据库失败**********************\033[0m\n");
sleep(2);
continue;
}
else if(strcmp(query_data,"d")==0)
{
printf("\033[5;31m*******************注册失败************************\033[0m\n");
sleep(2);
continue;
}
else if(strcmp(query_data,"f")==0)
{
printf("\033[5;31m*****************账号查找出错***********************\033[0m\n");
sleep(2);
continue;
}
else
{
printf("\033[5;31m*************账号已存在,请重新输入*****************\033[0m\n");
sleep(2);
continue;
}
}
else if(strcmp(query_data,"2")==0)
{
system("clear");
char account_number[32]={0},the_code[32]={0};
printf("\033[35m 进入登陆系统 \033[0m\n");
printf("\033[35m 输入你的账号(32位以内) \033[0m\n");
scanf("%s",account_number);
sendto(sockfd,account_number,sizeof(account_number),0,NULL,0);
printf("\033[35m 输入你的密码(32位以内) \033[0m\n");
scanf("%s",the_code);
sendto(sockfd,the_code,sizeof(the_code),0,NULL,0);
recvfrom(sockfd,query_data,sizeof(query_data),0,NULL,NULL);
printf("%s\n",query_data);
if(strcmp(query_data,"a")==0)
{
system("clear");
printf("\033[5;31m*******************登陆成功************************\033[0m\n");
sleep(2);
if(query_data[0]>=0)
{
while(1)
{
system("clear");
printf("\033[5;35m**********************************************************\033[0m\n");
printf("\033[5;35m**\033[0m 当前在查询系统 \033[5;35m**\033[0m\n");
printf("\033[5;35m**\033[0m 0退出 1查询单词 2查看历史查询记录 \033[5;35m**\033[0m\n");
printf("\033[5;35m**********************************************************\033[0m\n");
scanf("%s",query_data);
sendto(sockfd,query_data,sizeof(query_data),0,NULL,0);
if(strcmp(query_data,"0")==0)
{
printf("\033[5;31m*******************将返回上一级**********************\033[0m\n");
sleep(2);
break;
}
else if(strcmp(query_data,"1")==0)
{
system("clear");
printf("\033[5;31m**********现在正在进行单词查询,输入0可返回上一级************\033[0m\n");
sleep(3);
while(1)
{
char data_flag[128]={0};
printf("\033[31minpit>\033[0m");
scanf("%s",query_data);
strcpy(data_flag,query_data);
sendto(sockfd,query_data,sizeof(query_data),0,NULL,0);
if(strcmp(query_data,"0")==0)
{
printf("\033[5;31m**********************将返回上一级***********************\033[0m\n");
sleep(2);
break;
}
recvfrom(sockfd,query_data,sizeof(query_data),0,NULL,NULL);
if(strcmp(query_data,"a")==0)
{
recvfrom(sockfd,query_data,sizeof(query_data),0,NULL,NULL);
printf("\033[35m%s: %s\n\033[0m",data_flag,query_data);
history_data(account_number,data_flag,query_data);
}
else if(strcmp(query_data,"d")==0)
{
printf("\033[5;31m**********************查无此单词***********************\033[0m\n");
continue;
}
else
{
printf("\033[5;31m**********************未知错误,请联系管理人员***********************\033[0m\n");
continue;
}
}
}
else if(strcmp(query_data,"2")==0)
{
system("clear");
char back_data[4096]={0};
printf("\033[5;31m********************正在进行历史记录查询**********************\033[0m\n");
history_seek(account_number,back_data);
printf("\033[35%s\033[0m\n",back_data);
printf("\033[5;31m********************0返回上一级其他数字继续********************\033[0m\n");
int flag_l;
scanf("%d",&flag_l);
sendto(sockfd,&flag_l,1,0,NULL,0);
if(flag_l==0)
{
break;
}
else
{
continue;
}
}
else
{
printf("\033[5;31m*********************输入错误请重新输入************************\033[0m\n");
sleep(2);
continue;
}
}
}
continue;
}
else if(strcmp(query_data,"b")==0)
{
printf("\033[5;31m****************打开数据库失败**********************\033[0m\n");
sleep(2);
break;
}
else if(strcmp(query_data,"e")==0)
{
printf("\033[5;31m*******************无此账号*************************\033[0m\n");
sleep(2);
continue;
}
else if(strcmp(query_data,"c")==0)
{
printf("\033[5;31m*******************匹对失败*************************\033[0m\n");
continue;
}
else
{
printf("\033[5;31m*******************密码错误*************************\033[0m\n");
sleep(2);
continue;
}
}
else
{
printf("\033[5;31m**********************输入错误,重新输入***************************\033[0m\n");
sleep(2);
continue;
}
}
}
close(sockfd);
return 0;
}
服务器
在服务器中首先需要做的就是判断是否有新的客户端进行连接,如果有新的客户端进行了连接,则需要循环读取判断客户端是否有新的信息发送过来,如果有则需要将接收客户端发过来的信息进行识别判断,如果在数据库中找到相应的单词返回单词的含义返回给客户端,若没发现对应单词含义则返回错误提示符号。
下面是服务器的相应代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdlib.h>
#include "database_usrdata_lan.h"
#include "database_usrdata.h"
#include "database_seek.h"
#include "database_import.h"
int tcp_init(int arg);
int wait_accept(int arg);
int tcp_init(int hton)
{
int sockfp=socket(AF_INET,SOCK_STREAM,0);
if(sockfp<0)
{
perror("socket");
return -1;
}
int opt = 1;
if(setsockopt(sockfp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0){
perror("setsockopt");
return -1;
}
struct sockaddr_in addr;
addr.sin_family =AF_INET;
addr.sin_port =htons(hton);
addr.sin_addr.s_addr=htonl(INADDR_ANY);
if(bind(sockfp,(struct sockaddr*)&addr,sizeof(addr))<0)
{
perror("bind");
return -1;
}
if(listen(sockfp,12)<0)
{
perror("listen");
return -1;
}
return sockfp;
}
int wait_accept(int arg)
{
struct sockaddr_in caddr;
socklen_t len=sizeof(caddr);
int fp=accept(arg,(struct sockaddr*)&caddr,&len);
if(fp<0)
{
perror("accept");
return -1;
}
return fp;
}
int main(int argc, char *argv[])
{
system("clear");
int fp=tcp_init(2234);
if(fp<0)
{
printf("tcp_init:create not sucess");
return -1;
}
database_import();
printf("服务器初始化成功,等待客户端连接\n");
pid_t len_flag;
while(1)
{
int fq=wait_accept(fp);
if(fq<0)
{
continue;
}
printf("有客户端连接成功\n");
len_flag=fork();
if(len_flag==0)
{
while(1)
{
char buf[128]={0};
int num=recvfrom(fq,buf,sizeof(buf),0,NULL,NULL);
if(num<0)
{
perror("sendto");
break;
}
else if(num==0)
{
continue;
}
else
{
if(strcmp(buf,"1")==0)
{
char account_number[32]={0},the_code[32]={0};
if(recvfrom(fq,account_number,sizeof(account_number),0,NULL,NULL)==0)
{
printf("有客户端断开连接\n");
break;
}
if(recvfrom(fq,the_code,sizeof(the_code),0,NULL,NULL)==0)
{
printf("有客户端断开连接\n");
break;
}
bzero(buf,0);
buf[0]=database_usrdata(account_number,the_code);
sendto(fq,buf,sizeof(buf),0,NULL,0);
continue;
}
else if(strcmp(buf,"2")==0)
{
char account_number[32]={0},the_code[32]={0};
if(recvfrom(fq,account_number,sizeof(account_number),0,NULL,NULL)==0)
{
printf("有客户端断开连接\n");
break;
}
if(recvfrom(fq,the_code,sizeof(the_code),0,NULL,NULL)==0)
{
printf("有客户端断开连接\n");
break;
}
bzero(buf,0);
buf[0]=database_usrdata_lan(account_number,the_code);
printf("%s\n",buf);
sendto(fq,buf,sizeof(buf),0,NULL,0);
if(strcmp(buf,"a")==0)
{
while(1)
{
if(recvfrom(fq,buf,sizeof(buf),0,NULL,NULL)==0)
{
break;
}
if(strcmp(buf,"1")==0)
{
while(1)
{
char buf_seek[128]={0},flag_seek[128]={0};
if(recvfrom(fq,buf,sizeof(buf),0,NULL,NULL)==0)
{
break;
}
if(strcmp(buf,"0")==0)
{
break;
}
flag_seek[0]=database_seek(buf,buf_seek);
sendto(fq,flag_seek,sizeof(flag_seek),0,NULL,0);
if(strcmp(flag_seek,"a")==0)
{
printf("%s\n",buf_seek);
sendto(fq,buf_seek,sizeof(buf_seek),0,NULL,0);
}
else
{
continue;
}
}
}
else if(strcmp(buf,"2")==0)
{
int flag_l;
if(recvfrom(fq,&flag_l,1,0,NULL,NULL)==0)
{
break;
}
if(flag_l==0)
{
break;
}
else
{
continue;
}
}
else if(strcmp(buf,"0")==0)
{
break;
}
else
{
continue;
}
}
}
else
{
continue;
}
}
else
{
printf("有客户端断开连接\n");
break;
}
}
}
printf("有客户端断开连接\n");
close(fq);
}
}
close(fp);
return 0;
}
数据库
本项目中主要用到的数据是sqlite3,在数据库的操作上主要用到的了数据库的插入和查询。
下面是数据库的插入代码:
#include "database_usrdata.h"
char database_usrdata(char *usr_data, char *usr_lan)
{
sqlite3 *db;
if(sqlite3_open("database.db",&db)!=SQLITE_OK)
{
return 'b';
}
char sql[128]={0},**resultp;
int nrow,ncloumn;
sprintf(sql,"create table if not exists usrlan_data(name text,content text);");
if(sqlite3_exec(db,sql,NULL,NULL,NULL)!=SQLITE_OK)
{
return 'c';
}
sprintf(sql,"select content from usrlan_data where name='%s';",usr_data);
if(sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,NULL)!=SQLITE_OK)
{
return 'f';
}
if(resultp[ncloumn]==NULL)
{
bzero(sql,0);
sprintf(sql,"insert into usrlan_data values('%s','%s');",usr_data,usr_lan);
if(sqlite3_exec(db,sql,NULL,NULL,NULL)!=SQLITE_OK)
{
return 'd';
}
return 'a';
}
return 'e';
}
数据库查询代码:
#include "database_seek.h"
char database_seek(char *squery_data,char *buf)
{
sqlite3 *db;
if(sqlite3_open("database.db",&db)!=SQLITE_OK)
{
return 'b';
}
char sql[128]={0},**retulse;
int nrow,ncloumn;
sprintf(sql,"select content from dictionary where name='%s';",squery_data);
if(sqlite3_get_table(db,sql,&retulse,&nrow,&ncloumn,NULL)!=SQLITE_OK)
{
sqlite3_close(db);
return 'c';
}
if(ncloumn==0)
{
sqlite3_close(db);
return 'd';
}
else
{
strcpy(buf,retulse[ncloumn]);
}
sqlite3_close(db);
return 'a';
}
章末
以上便是整个英语词典项目的主要内容,完整代码笔者将放置在文章中。