电子词典项目

16. 电子词典项目需求

项目要求:

  1. 登录注册功能,不能重复登录,重复注册
  2. 单词查询功能
  3. 历史记录功能,存储单词,意思,以及查询时间
  4. 基于TCP,支持多客户端连接
  5. 采用数据库保存用户信息与历史记录
  6. 将dict.txt的数据导入到数据库中保存。
  7. 按下ctrl+c退出客户端后,注销该客户端的登录信息

格式要求:

  1. main函数只跑逻辑,不允许跑功能代码
  2. 功能代码封装成函数
  1. 先分析需求
  2. 将上述需求用流程图画出来
  3. 根据流程图搭建代码框架
  4. 一个功能一个功能实现

 流程图:

http://t.csdn.cn/ScQSW

网络编程电子词典项目:

目录

项目要求:

格式要求:

 流程图:

服务器代码

客户端

实现效果

服务器代码

头文件

#ifndef __FUNC_H__          
#define __FUNC_H__          
#include <sqlite3.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <stdlib.h>    
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#define PORT 6666              
#define IP "192.168.100.17"        
typedef void (*sighandler_t)(int);
#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:__%d__\n",__LINE__);\
	perror(msg);\
}while(0)    

struct msg{                          
    char type;             //消息类型
    char name[128];    //名字        
    char password[128];   //密码     
    char word[128];       //单词     
    char trans[128];      //翻译     
    char time[256];       //时间     
}sermsg;                             
                                   
sqlite3* sqlite3_database();  //创建数据库表
int cli_net();            //创建套接字.链接客户端.绑定信息结构体
int sqlite3_close(sqlite3* db);   //关闭数据库
int sqlite3_word(sqlite3* db);  //导入单词函数
int sqlite3_worddelete(sqlite3 *db);   //删除单词表函数
int ser_recv(int newfd,struct sockaddr_in cin);  //接收函数
int do_login(int newfd);   //登录函数
int do_register(int newfd);   //注册函数
int do_find(int newfd);       //查询单词
int do_history(int newfd);     //查询历史记录
int do_quit(int newfd);  //退出
void handler(int sig);    //捕获僵尸进程
              
#endif    

功能文件

#include "01_serfunc.h"

sqlite3 *db=NULL;
char *errmsg=NULL;

sqlite3* sqlite3_database()
{
	//创建并打开一个数据库
	if(sqlite3_open("./word.db",&db)!=SQLITE_OK)
	{
		fprintf(stderr,"line:%d sqlite3_open failed:%d:%s\n",\
				__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
		return NULL;
	}
	printf("sqlite3_open success\n");
	//删除单词表
	sqlite3_worddelete(db);
	//创建一张表格,数据库中sql怎么写就怎么写
	char sql[128]="create table if not exists wordbase(word char,explain char);";


	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
		return NULL;
	}
	printf("table stu create success\n");
	//创建一张表格 用于保存用户注册信息
	bzero(sql,sizeof(sql));
	sprintf(sql,"create table if not exists userbase(user char primary key,password char);");

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
		return NULL;
	}
	printf("table userbase create success\n");
	//创建一张表格 用于存储用户登录信息
	bzero(sql,sizeof(sql));
	sprintf(sql,"create table if not exists recordbase(user char primary key);");

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
		return NULL;
	}
	printf("table recordbase create success\n");


	//创建一张表格 用于存储用户历史查询信息                                              
	bzero(sql,sizeof(sql));                                                          
	sprintf(sql,"create table if not exists historybase(user char,word char,trans char,time char);");

	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)                            
	{                                                                                
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);                 
		return NULL;                                                                    
	}                                                                                
	printf("table historybase create success\n");
	//导入单词函数
	sqlite3_word(db);
	return db;

}
int sqlite3_close(sqlite3* db)   //关闭数据库
{
	//关闭数据库    
	if(sqlite3_close(db)!=SQLITE_OK)
	{
		fprintf(stderr,"line:%d sqlite3_close failed:%d:%s\n",\
				__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
		return-1;
	}
	return 0;
}
int sqlite3_word(sqlite3 *db)  //导入单词函数
{
	//打开一个文件
	FILE *fd=fopen("./dict.txt","r");
	if(NULL==fd)
	{
		perror("fopen");
		return -1;
	}
	printf("电子词典正在导入请稍后>>>\n");
	//指定的文件中格式化获取数据
	//存储每一行数据
	char buf[512]="";
	char get_word[128]="";
	char get_explain[128]="";
	char sql[128]="";
	char *errmsg=NULL;
	//循环读取每一行内容
	while(1)
	{
		bzero(get_word,sizeof(get_word));
		bzero(get_explain,sizeof(get_explain));

		if(fgets(buf,sizeof(buf),fd)==NULL)
		{                                                                                               
			printf("单词导入完毕\n");
			return -1;
		}
		buf[strlen(buf)-1]='\0';
		for(int i=0;i<buf[i+2] ;i++)
		{
			if(buf[i]!=' ' && buf[i+1]==' ' && buf[i+2]==' ')
			{
				strncpy(get_word,buf,i+1);
			}
			else if(buf[i]==' ' && buf[i+1]==' ' && buf[i+2]!=' ')
			{
				strcpy(get_explain,buf+i+2);
				break;
			}
		}
		bzero(sql,sizeof(sql));
		sprintf(sql,"insert into wordbase values(\"%s\",\"%s\");",get_word,get_explain);

		if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
			return-1;
		}
	}
	//关闭文件描述符
	fclose(fd);
	return 0;
}
int sqlite3_worddelete(sqlite3 *db)   //删除单词表函数
{
	char sql[128]="drop table wordbase;";
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)                            
	{                                                                                
		//	fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);                 
		return-1;                                                                    
	}                                                                                
	printf("worddelete success\n");
	return 0;
}
int ser_recv(int fd,struct sockaddr_in cin) //接收函数
{
	int newfd=fd;
	ssize_t res=0;
	while(1)
	{
		//bzero(&sermsg,sizeof(sermsg));
		res=recv(newfd,&sermsg,sizeof(sermsg),0);
		struct msg sermsg1;
		strcpy(sermsg1.name,sermsg.name);
		printf("%s\n",sermsg1.name);

		if(res<0)
		{
			return -1;
		}
		else if(0==res)
		{
			fprintf(stderr,"[%s:%d]newfd = %d 客户端下线\n",\
					inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
			//删除登录信息
			char sql[521];                                              
			char *errmsg=NULL;                                          
			sprintf(sql,"delete from recordbase where user=\"%s\";",sermsg1.name);                       
			//printf("%s\n",sql);
			if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)       
			{                                                   
				fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
				return 0;
			}

			return 0;

		}
		char choose=sermsg.type;	
		switch(choose)
		{
		case '1':  //注册
			do_register(newfd);
			break;
		case '2':   //登录
			do_login(newfd);
			break;
		case '4':  //查询
			do_find(newfd);
			break;
		case '5':  //历史记录
			do_history(newfd);     //查询历史记录
			break;
		case '6':  //退出
			do_quit(newfd);
			break;
		}
	}
	return 0;
}
//捕获僵尸进程
void handler(int sig)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
    return ;
}

int cli_net()//创建套接字.链接客户端.绑定信息结构体
{
	//创建流式套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	//允许端口快速重用
	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("允许端口快速重用\n");
	//填充地址信息结构体
	struct sockaddr_in sin; //定义结构体变量
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);
	//绑定信息结构体
	if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
	{                                                                                
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success\n");
	//将套接字设置为监听状态
	if(listen(sfd,5)<0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success\n");
	return sfd;
}
int do_quit(int newfd)
{
	//删除登录信息                                                         
	char sql[256];                                                         
	char *errmsg=NULL;                                                     
	sprintf(sql,"delete from recordbase where user=\"%s\";",sermsg.name);           
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)                  
	{                                                                      
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);       
		return 0;                                                          
	}                                                                      
	return 0;                                                              
}
int do_history(int newfd)    //查询历史记录
{
	//将数据包发送给客户端  根据登录名进行遍历查找记录表
	char sql[256]="";
	sprintf(sql,"select *from historybase where user=\"%s\";",sermsg.name);
	char **pres = NULL;   //存储结果
	int row, column;  //查询到的结果的行数;查询到的结果的列数
	char* errmsg = NULL;

	if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
	{
		fprintf(stderr, "line:%d sqlite3_get_table:%s\n", __LINE__, errmsg);
		return -1;
	}
	printf("row=%d column=%d\n", row, column);   //打印行和列
	bzero(sermsg.name,sizeof(sermsg.name));
	bzero(sermsg.word,sizeof(sermsg.word));
	bzero(sermsg.trans,sizeof(sermsg.trans));
	bzero(sermsg.time,sizeof(sermsg.time));

	int i=0;
	for(i=0; i<(row+1)*column; i++)
	{
		if(i%column == column-4)
			sprintf(sermsg.name,"%s",pres[i]);
		else if(i%column == column-3)
			sprintf(sermsg.word,"%s",pres[i]);
		else if(i%column == column-2)            
			sprintf(sermsg.trans,"%s",pres[i]);   
		else if(i%column == column-1)            
		{
			sprintf(sermsg.time,"%s",pres[i]);  
			if(send(newfd,&sermsg,sizeof(sermsg),0)<0)    
			{                                             
				ERR_MSG("send");                          
				return -1;                                
			}
		}
	}
	if(i==(row+1)*column)
	{
		sermsg.type='S';   //查询完成标注
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
	}
	if(i==0)
	{
		sermsg.type='F';   //查询完成标注
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
	}
	//释放内存空间
	sqlite3_free_table(pres);
	return 0;
}
//查询单词回调函数,满足就会执行                                                                         
int find_callBack(void *arg, int column, char **column_text, char **column_name)  //void* arg = &flag  
{          

	strcat(sermsg.trans,column_text[1]);
	strcat(sermsg.trans,"\n");
	sermsg.type='S';                               
	fprintf(stderr,"查询单词成功\n"); 
	(*(int *)arg)++;
	return 0;                                                                                           
}                                                                                                       

int do_find(int newfd)    //查询单词函数
{

	//清空翻译
	bzero(sermsg.trans,sizeof(sermsg.trans));
	char sql[512];                                                         
	char *errmsg=NULL;
	int flag=0;
	sprintf(sql,"select * from wordbase where word=\"%s\";",sermsg.word);  
	if(sqlite3_exec(db,sql,find_callBack,&flag,&errmsg)!=SQLITE_OK)       
	{ 
		sermsg.type='E';
		fprintf(stderr,"newfd = %d 查询单词失败\n",newfd);
		//将数据包发送给客户端                   
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)    
		{                                           
			ERR_MSG("send");                        
			return -1;                              
		}                 	
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
		return-1;                                            
	}
	if(flag==2)
	{
		//将数据包发送给客户端                         
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)     
		{                                              
			ERR_MSG("send");                           
			return -1;                                 
		}
	}
	else{
		//将数据包发送给客户端
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
	}
	//将查询信息插入到recordbase表格中
	//查询时间
	time_t t1;
	struct tm* timeinfo=NULL;
	time(&t1);
	timeinfo=localtime(&t1);
	char time1[256]="";
	sprintf(time1,"%d-%d-%d %d:%d:%d\n",timeinfo->tm_year+1900,timeinfo->tm_mon+1,timeinfo->tm_mday,\
			timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
	//插入历史记录表
	bzero(sql,sizeof(sql));                                             
	errmsg=NULL;                                           
	sprintf(sql,"insert into historybase values(\"%s\",\"%s\",\"%s\",\"%s\");",\
			sermsg.name,sermsg.word,sermsg.trans,time1);                        
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)        
	{                                                            

		return 0;
	}
	return 0;
}
int do_register(int newfd)   //注册函数
{
	char sql[364];
	char *errmsg=NULL;
	sprintf(sql,"insert into userbase values(\"%s\",\"%s\");",\
			sermsg.name,sermsg.password);
	if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		sermsg.type='E';
		fprintf(stderr,"newfd = %d 注册失败\n",newfd);
		//将数据包发送给客户端                   
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)    
		{                                           
			ERR_MSG("send");                        
			return -1;                              
		}                 	
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
		return-1;
	}
	sermsg.type='S';
	fprintf(stderr,"newfd = %d 注册成功\n",newfd);

	//将数据包发送给客户端                   
	if(send(newfd,&sermsg,sizeof(sermsg),0)<0)    
	{                                           
		ERR_MSG("send");                        
		return -1;                              
	}                                 
	return 1;
}
//登录查询回调函数,满足就会执行
int login_callBack(void *arg, int column, char **column_text, char **column_name)  //void* arg = &flag
{
	if(strcmp(column_text[0],sermsg.name)==0 && strcmp(column_text[1],sermsg.password)==0)
	{
		sermsg.type='S';                                
		*(int *)arg=1;
	}
	return 0;
}
int do_login(int newfd)   //登录函数
{
	char sql[512];
	char *errmsg=NULL;
	int flag=0;
	sprintf(sql,"select * from userbase where user=\"%s\";",sermsg.name);
	if(sqlite3_exec(db,sql,login_callBack,&flag,&errmsg)!=SQLITE_OK)                  
	{   
		fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);                 
		return -1;                              
	}
	if(flag==0)
	{
		sermsg.type='E';
		fprintf(stderr,"newfd = %d 登录失败\n",newfd);
		//将数据包发送给客 户端
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
	}
	//说明注册信息表中有,可以登录,判断是否为登录状态
	else if(flag==1)
	{
		//将登陆信息保存到登录信息表中
		char sql[364];                                              
		char *errmsg=NULL;                                          
		sprintf(sql,"insert into recordbase values(\"%s\");",sermsg.name);                       
		if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)       
		{                                                           
			sermsg.type='R';
			fprintf(stderr,"登录重复\n");
			bzero(sermsg.name,sizeof(sermsg.name));
			//将数据包发送给客户端
			if(send(newfd,&sermsg,sizeof(sermsg),0)<0)
			{
				ERR_MSG("send");
				return -1;
			}
			fprintf(stderr,"line:%d sqlite3_exec:%s\n",__LINE__,errmsg);
			return 0;
		}
		fprintf(stdout,"%s 登录成功\n",sermsg.name);
		//设置为登录状态,登陆成功,将数据包发送给客户端                          
		if(send(newfd,&sermsg,sizeof(sermsg),0)<0)      
		{                                               
			ERR_MSG("send");                            
			return -1;                                  
		}    
	}
	return 0;
}

测试文件

#include "01_serfunc.h"
int main(int argc, const char *argv[])
{
	//捕获僵尸进程
	sighandler_t s = signal(SIGCHLD, handler);
    if(SIG_ERR == s)
    {
        perror("signal");
        return -1;
    }
	//创建套接字.链接客户端.绑定信息结构体
	int sfd=cli_net();
	//创建数据库导入单词
	sqlite3*db=sqlite3_database();
	//由于自动获取,只需要定义几个结构体变量进行接受,需要时直接访问里面成员即可
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	//从已经完成链接的队列头获取一个客户端的信息,
	//生成一个新的文件描述符,新的才是用于和客户端通信的文件描述符
	pid_t pid=0;
	while(1)
	{
		//父进程负责处理客户连接
		int newfd=accept(sfd,(struct sockaddr *)&cin,&addrlen);
		if(newfd<0)                                                                           
		{
			ERR_MSG("accept");
			return -1;
		}
		printf("[%s:%d] newfd=%d 连接成功\n",\
				inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
		//创建子进程
		pid=fork();
		if(pid==0)
		{
		//	printf("进入接收函数\n");
			close(sfd);
			//接收消息
			ser_recv(newfd,cin);
			//退出子进程
			close(newfd);
			exit(0);
		}
		else if(pid>0)
		{
		//	close(newfd);
		}
		else
		{
			ERR_MSG("fork");
			return -1;
		}
	}
	//关闭数据库
	sqlite3_close(db);
	return 0;
}

客户端

头文件

#ifndef __FUNC_H__
#define __FUNC_H__
#include <stdio.h>
#include <sys/types.h>       
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>

#define PORT 6666              
#define IP "192.168.100.17" 

#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:__%d__\n",__LINE__);\
	perror(msg);\
}while(0)

struct msg{
	char type;             //消息类型
	char name[128];    //名字
	char password[128];   //密码
	char word[128];       //单词
	char trans[128];      //翻译
	char time[256];       //时间
}climsg;

void pri_menu(); //主菜单
void sec_menu();    //查询菜单
int cli_login(int sfd);   //登录
int cli_register(int sfd);    //注册
int cli_find(int sfd);       //查找单词
int cli_history(int sfd);     //查询历史记录	
int clisend(int sfd);   //发送函数
int clirecv(int sfd);  //接收函数
int cli_quit(int sfd);   //退出函数
int net_ser();     //创建套接字.链接客户端.绑定信息结构体
#endif

功能文件

#include "02_clifunc.h"
void pri_menu()    //主菜单
{
	printf("------欢迎来到电子词典-----\n");
	printf("--------1.注册-------------\n");
	printf("--------2.登录-------------\n");
	printf("--------3.退出-------------\n");
	printf("---------------------------\n");
}
void sec_menu()    //查询菜单
{
	printf("------欢迎来到电子词典-----\n");
	printf("--------4.查询单词---------\n");
	printf("--------5.历史查询记录-----\n");
	printf("--------6.退出-------------\n");
	printf("---------------------------\n");
}
int cli_quit(int sfd)   //退出
{
	//封装协议                                  
	climsg.type='6';                            
	//将数据包发送给服务器                      
	if(send(sfd,&climsg,sizeof(climsg),0)<0)    
	{                                           
		ERR_MSG("send");                        
		return -1;                              
	}              
	return 0;
}
int cli_history(int sfd)//查询历史记录
{
	//封装协议                                         
	climsg.type='5';                                         
	//将数据包发送给服务器                             
	if(send(sfd,&climsg,sizeof(climsg),0)<0)           
	{                                                  
		ERR_MSG("send");                               
		return -1;                                     
	}
	while(1)
	{	
		//阻塞接收服务器的回复                             
		if(recv(sfd,&climsg,sizeof(climsg),0)<0)           
		{                                                  
			ERR_MSG("recv");                               
			return -1;                                     
		} 
		if(climsg.type=='S')
			break;
		if(climsg.type=='F')
		{
			fprintf(stdout,"没有查询记录!");
			break;
		}
		fprintf(stdout,"%s %s %s %s\n",climsg.name,climsg.word,climsg.trans,climsg.time);
	}
	return 1;

}
int cli_find(int sfd)       //查找单词
{
	//封装协议                                            
	climsg.type='4';                                      
	printf("请输入要查询的单词>>>\n");                      
	fgets(climsg.word,sizeof(climsg.word),stdin);         
	climsg.word[strlen(climsg.word)-1]=0;                        
	//将数据包发送给服务器                                
	if(send(sfd,&climsg,sizeof(climsg),0)<0)              
	{                                                     
		ERR_MSG("send");                                  
		return -1;                                        
	}                                                     

	//阻塞接收服务器的回复                                
	if(recv(sfd,&climsg,sizeof(climsg),0)<0)              
	{                                                     
		ERR_MSG("recv");                                  
		return -1;                                        
	} 
	if(climsg.type=='S')
	{
		fprintf(stderr,"%s\n",climsg.trans);
	}
	else if(climsg.type=='E')
	{
		fprintf(stderr,"查询失败,请检查单词是否正确\n");
		return -1;
	}

	return 0;
}
int cli_login(int sfd)   //登录
{
	//封装协议
	climsg.type='2';
	printf("请输入登录用户名>>>\n");
	fgets(climsg.name,sizeof(climsg.name),stdin);   
	climsg.name[strlen(climsg.name)-1]=0;           
	printf("请输入登录密码>>>\n");
	fgets(climsg.password,sizeof(climsg.password),stdin);
	climsg.password[strlen(climsg.password)-1]=0;   

	//将数据包发送给服务器                    
	if(send(sfd,&climsg,sizeof(climsg),0)<0)  
	{                                         
		ERR_MSG("send");                      
		return -1;                            
	}                                         

	//阻塞接收服务器的回复                    
	if(recv(sfd,&climsg,sizeof(climsg),0)<0)  
	{                                         
		ERR_MSG("recv");                      
		return -1;                            
	}                                         
	if(climsg.type=='S')                       
	{                                          
		fprintf(stderr,"登录成功\n");
		return 1;
	}                                          
	else if(climsg.type=='E')                          
	{                                                  
		fprintf(stderr,"登录失败,请检查密码或者先注册\n");     
		return -1;
	}  
	else if(climsg.type=='R')                              
	{                                                      
   	 	fprintf(stderr,"重复登录\n"); 
		return -1;
	}                                                      
	return 1;                                          
}

int cli_register(int sfd)    //注册
{
	//封装协议
	climsg.type='1';
	bzero(climsg.name,sizeof(climsg.name));
	bzero(climsg.password,sizeof(climsg.password));
	printf("请输入注册的用户名>>>\n");

	fgets(climsg.name,sizeof(climsg.name),stdin);
	climsg.name[strlen(climsg.name)-1]=0;
	printf("请输入注册的密码>>>\n");
	fgets(climsg.password,sizeof(climsg.password),stdin);
	climsg.password[strlen(climsg.password)-1]=0;
    //将数据包发送给服务器
	if(send(sfd,&climsg,sizeof(climsg),0)<0)
	{
		ERR_MSG("send");
		return -1;
	}

	//阻塞接收服务器的回复
	if(recv(sfd,&climsg,sizeof(climsg),0)<0)
	{
		ERR_MSG("recv");
		return -1;
	}
	if(climsg.type=='S')
	{
		fprintf(stderr,"注册成功,请登录\n");
	}
	else if(climsg.type=='E')
	{
		fprintf(stderr,"注册失败,请更换用户名\n");
	}
	return 0;
}
//创建套接字.链接客户端.绑定信息结构体
int net_ser()
{
	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);                                                     
	if(sfd < 0)
	{
		ERR_MSG("socket");
		return -1;
	}
	printf("socket success\n");
	//非必须绑定,连接服务器
	//填充地址信息结构体
	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;
	}
	printf("connect success\n");
	return sfd;

}

测试文件

#include "02_clifunc.h"

int main(int argc, const char *argv[])
{

	//创建套接字.链接服务器.绑定信息结构体
	int sfd=net_ser();
	char choose=0;
	char ct=0;
	while(1)
	{
START:  system("clear");
		pri_menu();  //主菜单界面   
		printf("请输入你的选项>>>\n");
		choose=getchar();
		while(getchar()!=10);
		switch(choose)
		{
		case '1':	
			//注册
			cli_register(sfd);
			break;
		case '2':
			//登录
			if(cli_login(sfd)>0)
			{
				while(1)
				{
				//进入查询菜单
				system("clear");
				sec_menu();
				printf("请输入你的选项>>>\n");
				ct=getchar();
				while(getchar()!=10);
				switch(ct)
				{
				case '4':
					//查询单词
					cli_find(sfd);
					break;
				case '5':
					//历史记录查询
					cli_history(sfd);
					break;
				case '6':
					//退出登录
					cli_quit(sfd);
					goto START;
				default:
					fprintf(stdout,"输入有误,请重新输入\n");
					break;
				}
				printf("输入任意字符清屏>>>\n");
				while(getchar()!=10);
				}
			case '3':
				//退出
				goto END;
				break;
			default:
				fprintf(stdout,"输入有误,请重新输入\n");
				break;
			}
		}
		printf("输入任意字符清屏>>>\n");
		while(getchar()!=10);

	}
END:
	close(sfd);  //关闭套接字   
	return 0;
}

实现效果

注册

 登录

查询单词

 查询历史记录

 退出第查询界面,清空登录状态

 退出第一层界面,客户端下线

 重复登录

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值