项目:电子词典项目

服务器

。h

#ifndef __DICT_H__
#define __DICT_H__
#include<stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h> 
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include<sqlite3.h>
#include<stdlib.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define PORT 2223
#define IP "192.168.31.32"
#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:%d",__LINE__);\
	perror(msg);\
}while(0)

typedef struct cli_msg
{
	char type; //L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录
	char name[20];//登录姓名
	int password;//登录密码
	char word[666];//需要查询的单词
	int status;//登录状态    
}Msg;
//历史记录包
typedef struct {
	char type;//Y发送完N表示没发送完
	char data[1000];//历史记录包
}His;
//变更用户状态值
int ChangeUserStatus(Msg rcvbuf,sqlite3*db,int status);
//遍历数据库
int*do_select(sqlite3*db);
//建立数据库表格存储个人历史记录
int StoreHistory(Msg rcvbuf,sqlite3*db,char*pres);
//创建身份密码表ID
int CreateLogin();
//创建历史记录表History
int CreateHistoryWord();
//单词导入数据库
int InsertWord_database();
//登录
int do_login(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//注册
int do_SignIn(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
int do_LookUpWord(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//查询单词历史记录
int do_LookUpHistory(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//注销删除历史记录
int do_quit(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
//客户端普通退出
int do_exit(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db);
#endif

function。c

#include"dict.h"
//遍历数据库
int *do_select(sqlite3*db)
{
	char sql[128]="select *from dict";
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return NULL;
	}
	printf("row=%d,column=%d\n",row,column);
	int *p=&column;
	//释放查询的结果
	sqlite3_free_table(pres);
	return p;
}
//单词导入数据库
int InsertWord_database()
{
	sqlite3*db=NULL;
	if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
				__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
		return -1;
	}
	printf("open success\n");
	//创建表格
	char sql[128]="create table if not exists dict(word char,mean char);";
	printf("sql=%s\n",sql);
	char *errmsg=NULL;
	if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	//判断数据库单词的行数如果已经插入则不需要重复插入
	int *p=do_select(db);
	printf("%d:%d\n",__LINE__,*p);
	if(*p==0){
		//打开文件
		FILE*fd=fopen("./dict.txt","r");
		if(fd==NULL){
			perror("open");
			return -1;
		}
		//插入数据库
		char buf[128]="";
		char sql1[128]="";
		char arr[50]="";
		//char *errmsg=NULL;
		while(1){
			bzero(buf,sizeof(buf));
			bzero(arr,sizeof(arr));
			if(fgets(buf,sizeof(buf),fd)==NULL){
				printf("文件读取完毕\n");
				return -1;
			}
			buf[strlen(buf)-1]='\0';
			int i=0;
			char*p=buf;
			int j=0;
			while(buf[i]!=' '){
				p++;
				arr[j++]=buf[i++];
			}
			while(buf[i]==' '&&buf[i+1]!=' '){
				arr[j++]=' ';
				i++;
				while(buf[i]!=' '){
					p++;
					arr[j++]=buf[i++];
				}
			}
			while(buf[i++]==' '){
				p++;
			}
			sprintf(sql1,"%s (\"%s\",'%s')","insert into dict values",arr,p);
			printf("sql1=%s\n",sql1);
			if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
			{
				fprintf(stderr,"%d sqlite3_exec fail %s\n",\
						__LINE__,errmsg);
				return -1;
			}
		}
	}
	return 0;
}
//创建身份密码表
int CreateLogin()
{
	sqlite3*db=NULL;
	if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
				__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
		return -1;
	}
	printf("open success\n");
	//1表示有用户登录0表示没有用户登录
	char sql[128]="create table if not exists ID(name char,password int,status int);";
	printf("sql=%s\n",sql);
	char *errmsg=NULL;
	if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	return 0;
}
//变更用户状态值0表示没有用户登录1表示有用户登录
int ChangeUserStatus(Msg rcvbuf,sqlite3*db,int status)
{
	char sql1[128]="";
	//设置登录状态0表示没有用户登录
	sprintf(sql1,"%s%d %s'%s'","update ID set status=",status," where name=",rcvbuf.name);
	char *errmsg=NULL;
	printf("sql=%s\n",sql1);
	if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
	}
	return -1;
}
//取出数据库的状态值
int getstatus(Msg rcvbuf,sqlite3*db, int *pstatus)
{
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	char sql[128]="";
	sprintf(sql,"%s'%s'","select *from ID where name=",rcvbuf.name);
	printf("%d:sql=%s\n",__LINE__,sql);
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	int status=atoi(pres[5]);
	printf("status = %d\n", status);
	*pstatus = status;
	return 0;
}

//登录Y表示登录成功N表示登录失败
int do_login(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db)
{
	//判断登录名是否存在数据库中
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	char sql[128]="select *from ID";
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	printf("row=%d,column=%d\n",row,column);
	//判断登录名是否存在数据库中
	int k;//k记录登录名在表中的位置
	int i = 0;
	for(i=0;i<(row+1)*column;i++){
		if(i%column==0&&i!=0){
			if(strcmp(rcvbuf.name,pres[i])==0){
				k=i;
				break;
			}
		}                             
	}
	//若遍历到结尾都没有找到相同的用户名,则发送N后退出
	if(i == (row+1)*column)
	{
		printf("用户名不存在\n");
		rcvbuf.type='N';
		if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
			ERR_MSG("send");
			return -1;
		}
		return 0;
	}
	//用户名存在可以登录
	rcvbuf.type='Y';
	printf("%d:status=%d\n",__LINE__,rcvbuf.status);
	//取出数据库的状态值
	getstatus(rcvbuf,db, &(rcvbuf.status));
	printf("%d:status=%d\n",__LINE__,rcvbuf.status);

	if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
		ERR_MSG("send");
		return -1;
	}
	if(1 == rcvbuf.status)
	{
		printf("%s用户已经在线\n", rcvbuf.name);
		return 0;
	}
	//接收密码信息
	while(1){
		rcvbuf.type='Y';
		int res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
		if(res<0){
			ERR_MSG("recv");
			return -1;
		}
		//遍历密码信息
		if(rcvbuf.password==atoi(pres[k+1])){
			printf("登录成功\n");
			//变更用户状态值为1;
			ChangeUserStatus(rcvbuf,db,1);
			rcvbuf.status=1;
			rcvbuf.type='Y';

			if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
				ERR_MSG("send");
				return -1;
			}
			break;
		}
		else{
			printf("密码输入错误\n");
			rcvbuf.type='N';
			if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
				ERR_MSG("send");
				return -1;
			}
			printf("重新输入\n");
		}
	}
	return 0;
}
//注册
int do_SignIn(struct sockaddr_in cin,Msg rcvbuf,int newfd,sqlite3*db)
{
	//判断登录名是否存在数据库中
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	char sql[128]="select *from ID";
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	printf("row=%d,column=%d\n",row,column);
	//判断登录名是否存在数据库中
	int flag=0;//0不存在1存在
	for(int i=0;i<(row+1)*column;i++){
		//只判断用户名那一列
		if(i%column==0&&i!=0){
			if(strcmp(rcvbuf.name,pres[i])==0){
				flag=1;
				break;
			}
		}                             
	}
	if(flag==1){
		if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
			ERR_MSG("send");
			return -1;
		}
		 printf("用户名存在\n"); 
	}
	else{
		//可以注册
		rcvbuf.type='Y';
		if(send(newfd,&rcvbuf,sizeof(rcvbuf),0)<0){
			ERR_MSG("send");
			return -1;
		}
		//插入信息进数据库
		int res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
		if(res<0){
			ERR_MSG("recv");
			return -1;
		}
		char sql1[128]="";
		int status=0;//设置登录状态0表示没有用户登录
		sprintf(sql1,"%s ('%s',%d,%d)","insert into ID values",rcvbuf.name,rcvbuf.password,status);
		char *errmsg=NULL;
		printf("sql=%s\n",sql1);
		if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
		{
			fprintf(stderr,"%d sqlite3_exec fail %s\n",\
					__LINE__,errmsg);
			return -1;
		}
		printf("send success\n");    
	}
	puts("************\n");
	return 0;
}
//查询单词
int do_LookUpWord(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
	//遍历数据库单词判断是否存在该单词
	printf("%d:%s\n",__LINE__,rcvbuf.name);
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	char sql[128]="select *from dict";
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	printf("row=%d,column=%d\n",row,column);
	//判断单词是否存在数据库中
	int flag=0;//0不存在1存在
	for(int i=0;i<(row+1)*column;i++){
		//只判断单词那一列
		if(i%column==0&&i!=0){
			if(strcmp(rcvbuf.word,pres[i])==0){
				//建立数据库表格存储历史记录
				StoreHistory(rcvbuf,db,pres[i+1]);
				rcvbuf.type='Y';
				//发送意思和单词
				sprintf(rcvbuf.word,"%s %s",rcvbuf.word,pres[i+1]);
				if(send(sfd,&rcvbuf,sizeof(rcvbuf),0)<0){
					ERR_MSG("send");
					return -1;
				}
				flag=1;
			}
		}                             
	}
	//没有查到
	if(flag==0){
		rcvbuf.type='N';
		if(send(sfd,&rcvbuf,sizeof(rcvbuf),0)<0){
			ERR_MSG("send");
			return -1;
		}
	} 
	return 0;
}
//建立数据库表格存储个人历史记录
int StoreHistory(Msg rcvbuf,sqlite3*db,char*pres)
{
	char sql[128];
	sprintf(sql,"%s %s (%s)","create table if not exists",rcvbuf.name,"word char,mean char,time char" );
	printf("sql=%s\n",sql);
	char *errmsg=NULL;
	if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	//得到查询的时间
	struct tm*info;
	time_t t1=time(NULL);
	info=localtime(&t1);
	char time[120];
	sprintf(time,"%d-%d-%d %d:%d:%d",info->tm_year+1900,info->tm_mon+1,info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);
	//将历史记录插入数据库
	char sql1[1000]="";
	sprintf(sql1,"%s %s %s(\"%s\",'%s','%s')","insert into" ,rcvbuf.name, "values",rcvbuf.word,pres,time);
	printf("%d:sql=%s\n",__LINE__,sql1);
	if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	return 0;
}
//查询单词历史记录
int do_LookUpHistory(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
	char sql[128];
	char**pres=NULL;
	int row,column;
	char*errmsg=NULL;
	sprintf(sql,"%s %s","select *from",rcvbuf.name);
	printf("sql=%s\n",sql);
	if(SQLITE_OK!=sqlite3_get_table(db,sql,&pres,&row,&column,&errmsg))
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	printf("row=%d,column=%d\n",row,column);
	//可能会出现沾包问题
	His H_data;
	H_data.type='N';
	for(int i=3;i<(row+1)*column;i++){
		bzero(&H_data,sizeof(H_data));
		//拼接历史记录/Y发送完N表示没发送完
		strcpy(H_data.data,pres[i]);
		ssize_t res=send(sfd,&H_data,sizeof(H_data),0);
		if(res<0){
			ERR_MSG("send");
			return -1;
		}
	}
	H_data.type='Y';
	if(send(sfd,&H_data,sizeof(H_data),0)<0){
		ERR_MSG("send");
	}
	return 0;
}
//注销删除历史记录
int do_quit(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
	//从登录表中删除个人信息
	char sql[128]="";
	sprintf(sql,"%s'%s'","delete from ID where name=",rcvbuf.name);
	printf("sql=%s\n",sql);
	char *errmsg=NULL;
	if(SQLITE_OK!=sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	//删除个人的历史记录表
	char sql1[128]="";
	sprintf(sql1,"%s '%s'","drop table",rcvbuf.name);
	printf("sql=%s\n",sql1);
	if(SQLITE_OK!=sqlite3_exec(db,sql1,NULL,NULL,&errmsg)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_exec fail %s\n",\
				__LINE__,errmsg);
		return -1;
	}
	return 0;
}
//客户端普通退出
int do_exit(struct sockaddr_in cin,Msg rcvbuf,int sfd,sqlite3*db)
{
	//变更用户状态值0表示没有用户登录1表示有用户登录
	ChangeUserStatus(rcvbuf,db,0);
	return -1;
}

main。c

#include"dict.h"
void task(int arg)
{
	while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{ 
	//回收僵尸进程
	typedef void (*sighandler_t)(int);
	sighandler_t s=signal(17, task);
	//创建流套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	printf("socket success __%d__\n",__LINE__);
	//允许端口快速复用
	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0){
		ERR_MSG("setsockopt");
		return -1;
	}
	//填充结构体
	struct sockaddr_in sin;
	sin.sin_family= AF_INET;
	sin.sin_port=htons(PORT);
	//IP网络字节序
	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 __%d__\n",__LINE__);
	//监听
	if(listen(sfd,128)<0){
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success __%d__\n",__LINE__);
	//获取连接成功的文件描述符//NEWFD才是通信的描述符号//获取客户端的信息结构体
	struct sockaddr_in cin; 
	socklen_t addrlen=sizeof(cin);
	int newfd=-1;
	//单词导入数据库
	//遍历数据库,如果数据库行数小于不导入
	printf("正在导入\n");
	InsertWord_database();
	printf("导入成功\n");

	//创建身份密码表
	printf("创建身份密码表\n");
	CreateLogin();
	printf("创建身份密码表成功\n");

	//打开数据库
	sqlite3*db=NULL;
	if(sqlite3_open("./dict.db",&db)!=SQLITE_OK)
	{
		fprintf(stderr,"%d sqlite3_open fail %d|%s\n",\
				__LINE__,sqlite3_errcode(db),sqlite3_errmsg(db));
		return -1;
	}
	printf("open success\n");
	//接收数据
	while(1){
		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_t pid=fork();
		if(pid==0){
			//关闭套接字
			close(sfd);
			//执行程序
			Msg rcvbuf;
			int res;
			int status=0;//-1表示客户端正常退出,0表示ctrl+C退出
			bzero(rcvbuf.name,sizeof(rcvbuf.name));
			//L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录
			while(1)
			{
				//bzero(rcvbuf.name,sizeof(rcvbuf.name));
				res=recv(newfd,&rcvbuf,sizeof(rcvbuf),0);
				if(res<0){
					ERR_MSG("recv");
					return -1;
				}
				else if(res==0){
					fprintf(stderr,"[%s : %d] newfd=%d,客户端下线\n",\
							inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
					if(status==0){
						//ctrl+c客户端下线删除历史记录和注销用户
						//printf("注销客户端信息及删除个人历史记录\n");
						printf("ctrl+c退出\n");
						do_quit(cin,rcvbuf,newfd,db);//注销删除历史记录
					}
					break;
				}
				printf("[%s : %d] newfd=%d\nC:%s\n",\
						inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,rcvbuf.name); 
				switch(rcvbuf.type)
				{
				case 'L': 	
					do_login(cin,rcvbuf,newfd,db);//登录
					break;
				case 'Z':
					do_SignIn(cin,rcvbuf,newfd,db);//注册
					break;
				case 'C':
					do_LookUpWord(cin,rcvbuf,newfd,db);//查询单词
					break;
				case 'H':
					do_LookUpHistory(cin,rcvbuf,newfd,db);//查询单词历史记录
					break;
				case 'Q':
					do_quit(cin,rcvbuf,newfd,db);//注销删除历史记录
					break;
				case 'X':
					status=do_exit(cin,rcvbuf,newfd,db);//客户端普通退出
					break;
				default:
					printf("协议 %c 错误 __%s__ __%d__\n", rcvbuf.type, __FILE__, __LINE__);
				}
			}
			close(newfd);
			exit(0);//退出子进程
		}
		else if(pid>0){
			//多客户端连接
			close(newfd);
		}
		else{
			ERR_MSG("fork");
			return 0;
		}
	}	
	//关闭数据库
	if(sqlite3_close(db)!=SQLITE_OK){
		fprintf(stderr,"%d sqlite3_close fail",__LINE__);
		return -1;
	}
	close(sfd);
	close(newfd);
	return 0;
}

客户端

#include<stdio.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h> 
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include<stdlib.h>
#include <signal.h>
#include <sys/types.h>

#define PORT 2223
#define IP "192.168.31.32"
#define ERR_MSG(msg) do{\
	fprintf(stderr,"line:%d",__LINE__);\
	perror(msg);\
}while(0)
//登录信息结构体
typedef struct cli_msg  
{                       
	char type;//L登录Z注册#退出查询C查询单词H查询历史记录Q注销删除历史记录  
	char name[20];//登录名
	int password;//登录密码
	char word[666];
	int status;//登录状态
}Msg;
//历史记录包                         
typedef struct {                     
    char type;//Y发送完N表示没发送完 
    char data[1000];//历史记录包          
}His;                                
//登录
Msg* do_login(int sfd)
{
	Msg sndbuf;
	char name[20]="";
	int password;
	int res;
	Msg*p=(Msg*)malloc(sizeof(Msg));//堆区申请空间保存用户名
	while(1){
		while(1){
			sndbuf.type='L';
			printf("请输入登录名或#退出登录\n");
			scanf("%s",name);
			strcpy(sndbuf.name,name);
			//退出到登录界面
			if(strcmp(sndbuf.name,"#")==0){
				strcpy(p->name,sndbuf.name);
				return p;
			}
			if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
				ERR_MSG("send");
				return NULL;
			}
			res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
			if(res<0){
				ERR_MSG("recv");
				return NULL;
			}
			if(sndbuf.type=='Y'){
				//0表示不在线1表示在线
				printf("%d:%d\n",__LINE__,sndbuf.status);
				if(sndbuf.status==0){
					printf("请输入密码\n");
					break;
				}
				else{
					printf("用户在线\n");
			 	}
			}
			printf("用户名不存在,请重新输入\n");
		}
		//sndbuf.type=Y表示登录成功
		while(1){
			int password;
			scanf("%d",&password);
			sndbuf.password=password;

			if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
				ERR_MSG("send");
				return NULL;
			}
			res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
			if(res<0){
				ERR_MSG("recv");
				return NULL;
			}
			if(sndbuf.type=='Y'){
				printf("登录成功\n");
				strcpy(p->name,sndbuf.name);
				return p;//返回登录名
			}
			printf("密码错误,请重新输入密码\n");
		}
	}
    return NULL;
}
//注册
int do_SignIn(int sfd)
{
	Msg sndbuf;
	sndbuf.type='Z';
	char name[20];
	int password;
	int res;
	while(1){
		while(1){
			printf("请输入注册名\n");
			scanf("%s",name);
			strcpy(sndbuf.name,name);
			if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
				ERR_MSG("send");
				return -1;
			}
			res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
			if(res<0){
				ERR_MSG("recv");
				return -1;
			}
			if(sndbuf.type=='Y'){
				printf("请输入密码\n");
				break;
			}
			printf("用户名已存在\n");
		}
		//sndbuf.type=Y表示注册成功
			int password;
			scanf("%d",&password);
			sndbuf.password=password;
			if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
				ERR_MSG("send");
				return -1;
			}
			printf("注册成功\n");
			break;
		}
    return 0;
}
//查询单词
int do_LookUpWord(Msg*name,int sfd)
{
	Msg sndbuf;
	strcpy(sndbuf.name,name->name);
	printf("%d:%s\n",__LINE__,sndbuf.name);  

	ssize_t res=-1;
	while(1){
		printf("请输入要查询的单词or # 退出查询\n");
		bzero(sndbuf.word,sizeof(sndbuf.word));
		scanf("%s",sndbuf.word);
		sndbuf.type='C';
		if(strcmp(sndbuf.word,"#")==0){
			break;
		}
		if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
			ERR_MSG("send");
			return -1;
		}
		//接收服务器的信息
		res=recv(sfd,&sndbuf,sizeof(sndbuf),0);
		if(res<0){
			ERR_MSG("recv");
			return -1;
		}
		//判断是否查到单词Y表示查询到单词N表示没有查询到单词
		if(sndbuf.type=='Y'){
			printf("%s\n",sndbuf.word);
		}
		else{
			printf("没有查询到这个单词\n");
		}
	}
	return 0;
}
//查询单词历史记录
int do_LookUpHistory(Msg*name,int sfd)
{
	Msg sndbuf;
	His H_data;//历史记录包
	strcpy(sndbuf.name,name->name);
	sndbuf.type='H';
	if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
		ERR_MSG("send");
		return -1;
	}
	//接收服务器的信息
	int i=0;//调整格式
	while(1){
		//清空数据包Y发送完N表示没发送完 
		bzero(&H_data,sizeof(H_data));
		ssize_t res=recv(sfd,&H_data,sizeof(H_data),0);
		if(res<0){
			ERR_MSG("recv");
			return -1;
		}
		i++;
		if(H_data.type=='Y'){
			//最后一个包退出
			puts("退出查询历史记录\n");
			break;
		}
		printf("%s\t",H_data.data);
		fflush(stdout);
		if(i%3==0){
			printf("\n");
		}
	}
    return 0;
}
//注销用户删除历史记录表
int do_quit(Msg*name,int sfd)
{
	Msg sndbuf;
	sndbuf.type='Q';
	strcpy(sndbuf.name,name->name);
	if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
		ERR_MSG("send");
		return -1;
	}
	printf("删除成功\n");
	//释放堆区空间
	free(name);
	name=NULL;
    return 0;
}
                                     
int main(int argc, const char *argv[])
{
	//创建流套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0){
		ERR_MSG("socket");
		return -1;
	}
	printf("socket success __%d__\n",__LINE__);
	//允许端口快速复用(不写绑定)
	//填充结构体
	struct sockaddr_in sin;
	sin.sin_family= AF_INET;
	sin.sin_port=htons(PORT);
	//IP网络字节序
	sin.sin_addr.s_addr=inet_addr(IP);
	
	if(-1==connect(sfd, (struct sockaddr*)&sin, sizeof(sin))){
		ERR_MSG("connet");
		return -1;
	}
	printf("connect  serve success\n");
	//登录操作
	int  choose;
	Msg*name=NULL;
	while(1){
BAGIN:
		printf("**************************\n");
		printf("**********1登录***********\n");
		printf("**********2注册***********\n");
		printf("**********3退出客户端*****\n");
		printf("**************************\n");
		printf("请输入>>>\n");
		scanf("%d",&choose);
		switch(choose){
		case 1:
			name=do_login(sfd);//登录信息
			printf("%d:%s\n",__LINE__,name->name);
			if(strcmp(name->name,"#")==0){
				goto BAGIN;
			}
			break;
		case 2:
			do_SignIn(sfd);//注册
			goto BAGIN;
		case 3:
			goto END;
		default:
			printf("输入错误,请重新输入\n");
			goto BAGIN;
		}
		Msg sndbuf;
		//查询操作
		while(1){
			printf("****************************\n");
			printf("**********1查询单词*********\n");
			printf("**********2查询历史记录*****\n");
			printf("**********3注销用户*********\n");
			printf("**********4退出用户重新登录*\n");
			printf("**********5退出客户端*******\n");
			printf("****************************\n");
			printf("请输入>>>\n");
			getchar();
			scanf("%d",&choose);
			switch(choose){
			case 1:
				do_LookUpWord(name,sfd);//查询单词
				break;
			case 2:
				do_LookUpHistory(name,sfd);//查询单词历史记录
				break;
			case 3:
				do_quit(name,sfd);//注销用户删除历史记录表
				goto BAGIN;
			case 4:
				sndbuf.type='X';
				strcpy(sndbuf.name,name->name);
				printf("%d:%s\n",__LINE__,name->name);
				if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
					ERR_MSG("send");
					return -1;
				}
				goto BAGIN;
			case 5:
				sndbuf.type='X';
				strcpy(sndbuf.name,name->name);
				if(send(sfd,&sndbuf,sizeof(sndbuf),0)<0){
					ERR_MSG("send");
					return -1;
				}
				goto END;
			default:
				printf("输入错误__%d__\n", __LINE__);
			}
		}
	}
END:
	//释放堆区空间
	free(name);
	name=NULL;
	//关闭套接字
	close(sfd);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值