一、在线电子词典功能
大学生自己编写,如有问题多多指教!
1. 用户登录。
2. 用户注册(已有用户不能注册)。
3. 单词查询(根据客户端输入的单词,服务器可以根据文件查找反馈查询的单词和解释)。
4. 历史记录显示(查询单词时服务器会将历史记录存在数据库中,客户端接收数据库内容)。
5. 可同时登录多个用户。
二、服务器与客户端内容
1.服务器
代码如下(示例):
void create(void);//创建用户
void history(void);//历史记录
void login(void);//登录用户并查询
void query(void);//查询并写入历史记录表
int callback(void *arg,int f_num,char **f_value,char **f_name);//回调函数
sqlite3 *db;//数据库句柄
char name[32]="",password[32]="",sql[128]="";//用户名 密码 数据库执行语句
char *errmsg,num[32]="",num_1[32]="";//报错 页面1选择 页面2选择
int sockfd,acceptfd;//tcp
int ok_1=0;
void handler(int signum);
int main(int argc, const char *argv[])
{
char buf[128]="";
int z;
pid_t pid;
int s=1;
if(sqlite3_open("use.db",&db) != 0)//打开数据库
{
fprintf(stderr,"sqlite3_open failed: %s\n",sqlite3_errmsg(db));
exit(-1);
}
sqlite3_exec(db,"create table np(name char primary key,password char);",NULL,NULL,&errmsg);
sqlite3_exec(db,"create table jl(record char,time char);",NULL,NULL,&errmsg);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
{
perror("socket failed.");
exit(-1);
}
printf("socket ok.\n");
struct sockaddr_in serveraddr,clientaddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(8888);
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
socklen_t addrlen = sizeof(serveraddr);
socklen_t clientlen = sizeof(clientaddr);
int optval = 1;
socklen_t optval_len = sizeof(optval);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,optval_len);//允许地址重用
if(bind(sockfd,(struct sockaddr *)&serveraddr,addrlen) < 0)
{
perror("bind failed.");
exit(-1);
}
printf("bind ok.\n");
if(listen(sockfd,8) < 0)
{
perror("bind failed.");
exit(-1);
}
printf("listen ok.\n");
#if 1
signal(SIGCHLD,handler);//注册信号
while(1)
{
acceptfd = accept(sockfd,NULL,NULL);
printf("acceptfd ok.\n");
pid = fork();
if(pid < 0)
{
perror("fork failed.");
exit(-1);
}
if(pid == 0)
{
close(sockfd);
while(1)
{
z=recv(acceptfd,num,1,0);
if(z < 0)
{
printf("recv failed.\n");
}
if(z > 0)
{
switch(num[0])
{
case '1':create();break;
case '2':login();break;
case '3': exit(0);break;
}
}
}
close(acceptfd);
}
}
return 0;
}
#endif
/***********************************************************************************/
void create(void) //创建用户
{
bzero(num,32);//清空num否则一直进入循环
ssize_t t,p;
char cw[32]="The user name already exists";//用户名已存在
char cg[32]="Creating a successful";//创建成功
t=recv(acceptfd,name,sizeof(name),0);//接受用户名
if(t < 0)
{
perror("recv err");
exit(-1);
}
p=recv(acceptfd,password,sizeof(password),0);//接受密码
if(p < 0)
{
perror("recv err");
exit(-1);
}
sprintf(sql,"insert into np values(\"%s\",\"%s\");",name,password);
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != 0)//写入数据库
{
send(acceptfd,cw,sizeof(cw),0);//返回用户名存在
printf("%s\n",cw);
fprintf(stderr,"create failed %s\n",errmsg);
}
else
{
send(acceptfd,cg,sizeof(cg),0);//创建成功
printf("%s\n",cg);
}
bzero(name,32);
bzero(password,32);
bzero(sql,128);
}
/*************************************************************************************/
void login(void)//登录用户并查询
{
bzero(num,32);//清空num否则一直进入循环
ssize_t t,p;
int w=1;
t=recv(acceptfd,name,sizeof(name),0);//接受用户名
if(t < 0)
{
perror("recv err");
exit(-1);
}
p=recv(acceptfd,password,sizeof(password),0);//接受密码
if(p < 0)
{
perror("recv err");
exit(-1);
}
if(sqlite3_exec(db,"select * from np;",callback,"niugewudi",&errmsg) != 0)//回调函数
{
fprintf(stderr,"create failed %s\n",errmsg);
exit(-1);
}
if(ok_1==1)
{
while(w)
{
recv(acceptfd,num_1,sizeof(num_1),0);
switch(num_1[0])
{
case '1':query();break;
case '2':history();break;
case '3':w=0;break;
}
}
}
}
/*****************************************************************************/
int callback(void *arg,int f_num,char **f_value,char **f_name)//回调函数
{
int i,j=0;
char ok[32]="ok",no[32]="no";
char *sp=NULL,*fp=NULL;
sp=f_value[0];//用户名
fp=f_value[1];//密码
if(strcmp(name,sp) == 0)//比较用户名
{
if(strcmp(password,fp)==0)//比较密码
{
ok_1=1;
send(acceptfd,ok,sizeof(ok),0);
printf("login successfully\n");//登录成功!!!!
}
else
{
ok_1=0;
send(acceptfd,no,sizeof(no),0);
printf("password error\n");//密码错误
}
}
return 0;
}
/****************************************************************************/
void query(void)//查询并写入历史记录表
{
bzero(num_1,32);
FILE *tp;//打开文件流指针
tp=fopen("./1.txt","r");
char jl[32]="",jl_time[128]="",jl_yj[128]="",cx[128]="",cx_r[128]="",as[128]=" ";
time_t t;
struct tm *sp=NULL;
recv(acceptfd,jl,sizeof(jl),0);//输入的单词
strncpy(as,jl,strlen(jl));
t=time(&t);
sp=localtime(&t);
sprintf(jl_time,"%d-%d-%d,%d:%d:%d",sp->tm_year+1900,\
sp->tm_mon+1,sp->tm_mday,sp->tm_hour,\
sp->tm_min,sp->tm_sec);
printf("%s %s\n",jl,jl_time);
sprintf(jl_yj,"insert into jl values(\"%s\",\"%s\");",jl,jl_time);
if(sqlite3_exec(db,jl_yj,NULL,NULL,&errmsg) != 0)//历史记录,时间写入数据库
{
fprintf(stderr,"create failed %s\n",errmsg);
}
while(fgets(cx,128,tp)!=NULL)
{
if(strncmp(as,cx,strlen(as))==0)
{
strcpy(cx_r,cx);
break;
}
else
{
strcpy(cx_r,"No word was found");
}
bzero(cx,128);
}
send(acceptfd,cx_r,sizeof(cx_r),0);
}
/************************************************************************************/
void history(void)
{
bzero(num_1,32);
char **resultp;
int nrow;
int ncolumn;
sqlite3_get_table(db,"select * from jl;",&resultp,&nrow,&ncolumn,&errmsg);
int i,j,sum= 0;
char ppp[128]="";
for(i = 0;i < nrow + 1;i++)
{
for(j = 0;j < ncolumn;j++)
{
sprintf(ppp,"%s",resultp[sum++]);
printf("%s\n",ppp);
send(acceptfd,ppp,sizeof(ppp),0);
}
}
strcpy(ppp,"tuichu");
send(acceptfd,ppp,sizeof(ppp),0);
}
/*************************************************************************************/
void handler(int signum)
{
waitpid(-1,NULL,WNOHANG);//非阻塞
printf("signum = %d\n",signum);
}
2.客户端
代码如下(示例):
void create(void);//创建用户
void query(void);//查询并写入历史记录
void login(void);//登录用户并查询
void history(void);//历史记录
int sockfd;
char num[32]="";
char num_1[32]="";
int main(int argc, const char *argv[])
{
char buf[128] = {0};
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
perror("socket failed.");
exit(-1);
}
printf("socket ok.\n");
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
socklen_t addrlen = sizeof(serveraddr);
if(connect(sockfd,(struct sockaddr *)&serveraddr,addrlen) < 0)
{
perror("connect failed.");
exit(-1);
}
printf("connect ok.\n");
while(1)
{
printf("**************************************************\n");
printf("* 1.创建用户 2.登录用户并查询 3.退出 *\n");
printf("**************************************************\n");
printf("please choose:");
fgets(num,32,stdin);
num[strlen(num)-1]='\0';
send(sockfd,num,1,0);
switch(num[0])
{
case '1':create();break;
case '2':login();break;
case '3':return 0;break;
}
}
close(sockfd);
return 0;
}
/********************************************************************************/
void create(void) //创建用户
{
bzero(num,32);//清空num否则一直进入函数
char name[32]="",password[32]="",jg[32]="";
printf("Input name:");
fgets(name,32,stdin);//输入用户名
name[strlen(name)-1]='\0';//!!!!!!!!
printf("Input password:");
fgets(password,32,stdin);//输入密码
password[strlen(password)-1]='\0';//!!!!!!!!!!
send(sockfd,name,sizeof(name),0);//发送用户名
send(sockfd,password,sizeof(password),0);//发送密码
recv(sockfd,jg,sizeof(jg),0);
printf("%s\n",jg);
}
/*******************************************************************************/
void login(void)//登录用户并查询
{
bzero(num,32);//清空num否则一直进入函数
char name[32]="",password[32]="",zq[32]="";
int w=1;
printf("Input name:");
fgets(name,32,stdin);//输入用户名
name[strlen(name)-1]='\0';//!!!!!!!!
printf("Input password:");
fgets(password,32,stdin);//输入密码
password[strlen(password)-1]='\0';//!!!!!!!!!!
send(sockfd,name,sizeof(name),0);//发送用户名
send(sockfd,password,sizeof(password),0);//发送密码
recv(sockfd,zq,sizeof(zq),0);
while(w)
{
if(zq[0] == 'o')
{
printf("login successfully\n");
printf("**************************************************\n");
printf("* 1.查询 2.历史记录 3.quit *\n");
printf("**************************************************\n");
printf("please choose:");
fgets(num_1,32,stdin);
send(sockfd,num_1,sizeof(num_1),0);
switch(num_1[0])
{
case '1':query();break;
case '2':history();break;
case '3':w=0;break;
}
}
else
{
printf("No such user\n");//没用该用户
break;
}
}
}
/******************************************************************************/
void query(void)//查找函数
{
char jl[32]="",cx[128]="";
printf("Input word : ");
fgets(jl,32,stdin);//输入的单词
jl[strlen(jl)-1]='\0';
send(sockfd,jl,sizeof(jl),0);
recv(sockfd,cx,sizeof(cx),0);
if(cx[0]!='N')
{
printf("%s\n",cx+17);
}
else
{
printf("%s\n",cx);
}
}
/************************************************************************/
void history(void)//历史记录
{
bzero(num_1,32);
char ppp[128]="";
int p=0;
while(1)
{
recv(sockfd,ppp,sizeof(ppp),0);
if(strcmp(ppp,"tuichu")==0)
{
break;
}
printf("%-10s",ppp);
p++;
if(p%2==0)
{
putchar(10);
}
}
p=0;
}
总结
Linux下实现程序设计,基于C语言,利用TCP协议和多进程及Sqlite3数据库,实现多个客户端连接服务器,并实现用户注册登录、英译汉、显示查询历史记录等操作。
———————————————————
具体文件提取
百度网盘链接:https://pan.baidu.com/s/1sx0otIXcKsgUa2DIaY17Mg
提取码:1111