基于TCP模型的在线用户信息档案数据库管理系统<功能实现>

设计分析

思路分析

1、客户端和服务器之间利用结构体传输消息
2、结构体中消息类型作为操作码
3、usertype决定管理员还是普通用户
4、username决定账号
5、passwd存储密码
6、recvmsg存储通信的数据
7、标志位决定二级操作指定代号
8、info结构体中存储用户信息

实现步骤

1、TCP基础模型,实现服务器和客户端的基本连接
2、服务器设计多进程并发运行,在accept后创建子进程负责对相应连接客户端的交互
3、打开数据库,并创建相关数据表、历史记录表
4、在接受到客户端发送的数据信息后,对其进行处理并发送相应的回应包由客户端解析后进行下一步操作
5、在接收到数据时忘历史记录数据表中存储相关信息,并在服务器中进行打印
6、查看记录时可以运用get_table函数,并对其形参中的二级指针进行数据内容分析(数据内容存储方式类似一维数组,行列下标的乘积决定数据内容)
7、 客户端退出前,需要向服务器发送相关内容,服务器选择关闭当前交互进程并发送信号给父进程,回收其资源

代码实现

服务器

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

#define ADMIN 0	//管理员
#define USER  1	//用户

#define NAMELEN 16
#define DATALEN 128
/*员工基本信息*/
typedef struct staff_info{
	int  no; 			//员工编号
	int  usertype;  	//ADMIN 1	USER 2	 
	char name[NAMELEN];	//姓名
	char passwd[8]; 	//密码
	int  age; 			// 年龄
	char phone[NAMELEN];//电话
	char addr[DATALEN]; // 地址
	char work[DATALEN]; //职位
	char date[DATALEN];	//入职年月
	int level;			// 等级
	double salary ;		// 工资
	
}staff_info_t;
/*定义双方通信的结构体信息*/
typedef struct {
	int  msgtype;     //请求的消息类型
	int  usertype;    //ADMIN 1	USER 2
	char username[NAMELEN];  //姓名
	char passwd[8];			 //登陆密码
	char recvmsg[DATALEN];   //通信的消息
	int  flags;      //标志位
	staff_info_t info;      //员工信息
}MSG;

#define ADMIN 0	//管理员
#define USER  1	//用户

#define TABLE1 "staff_info" 
#define TABLE2 "history"
typedef void (*sighandler_t)(int);
//打印错误新的宏函数
#define ERR_MSG(msg)  do{\
	fprintf(stderr, " __%d__ ", __LINE__);\
	perror(msg);\
}while(0)

void handler(int sig)
{
	//回收僵尸进程
	//回收成功则再回收一次,直到回收失败或者没有回收到为止
	while(waitpid(-1, NULL, WNOHANG) > 0);
}

int do_select(sqlite3* db,MSG msg,int flag,struct sockaddr_in sin,int newfd);
int rcv_cli_msg(int newfd, struct sockaddr_in sin,MSG *msg);

int history(sqlite3 *db,char*beheivor,MSG msg);
int main(int argc, const char *argv[])
{
	//打开数据库
	sqlite3* db = NULL;
	if(sqlite3_open("./my.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 success\n");
	//创建一个表格存储账户
	char* sql = "create table if not exists staff_info (no int,usertype int,name char primary key,passwd char,age int,phone char,addr char,work char,date char,level int,salary double);" ;
	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 success\n");
	printf("create table success\n");




	//创建流式套接字
	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 ip
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(*(int*)argv[2]); 	//网络字节序的端口号
	sin.sin_addr.s_addr = inet_addr(argv[1]); 	//网络字节序的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");
	
	socklen_t addrlen = sizeof(sin);
	//捕获17号信号 SIGCHLD
	sighandler_t s = signal(SIGCHLD, handler);
	//从已完成连接的队列头中,取出一个客户端的信息,创建生成一个新的套接字文件描述符,
	//该文件描述符才是与客户端通信的文件描述符!!!
	while(1)
	{   
		struct sockaddr_in cin;
		int newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);
		if(newfd < 0)
		{
			perror("accept");
			return -1;
		}
		pid_t pid=fork();
		if(pid > 0)
		{
			close(newfd);
		}
		else if(0 == pid)
		{
			close(sfd);

			//网络字节序的IP-->点分十进制  网络字节序的port--->本机字节序
			printf("[%s : %d] newfd = %d\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),newfd);
			MSG msg={0};
			while(1)
			{
				recv(newfd,&msg,sizeof(msg),0);

				//rcv_cli_msg(newfd, cin,&msg);
				//printf("recv结束\n");
				do_select(db,msg,1,sin,newfd);
			}

			close(newfd);
			exit(0);
		}
	}

	close(sfd);
	return 0;
}
int rcv_cli_msg(int newfd, struct sockaddr_in cin,MSG *msg)
{
	ssize_t res = 0;
	bzero(&msg, sizeof(msg));
	//接收 
	res = recv(newfd, &msg, sizeof(msg), 0);
	if(res < 0)
	{
		ERR_MSG("recv");
		return -1;
	}
	else if(0 == res)
	{
		printf("[%s : %d] newfd = %d client off-line\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),newfd);
	}
	printf("[%s : %d] newfd = %d : %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),newfd, msg->recvmsg);

	return 0;
}

int send_ser_msg(int newfd,struct sockaddr_in sin,MSG msg)
{
				//发送数据
				if(send(newfd,&msg,sizeof(msg), 0) < 0)
				{
					ERR_MSG("send");
					return -1;
				}
				printf("send message success\n");
			
		return 0;
}



int do_select(sqlite3* db,MSG msg,int flag,struct sockaddr_in sin,int newfd)
{
	
    char sql[128] = "select *  from ";
	if(flag==1)
		strcat(sql,TABLE1);
	else
		strcat(sql,TABLE2);
    char ** pres = NULL;    //存储查询结果的首地址
    int row, column;        //查询结果的行列数
    char* errmsg = NULL;

    if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
    {
        fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
        return -1;
    }
    //能运行到当前位置则说明,查询函数运行成功


	switch(msg.msgtype)
	{
	case 0:
		{
			printf("case0\n");
			history(db,"登陆",msg);
			int i = 0;
			for(i=0; i<(row+1); i++)
			{

				if(strcmp(pres[i*column+2],msg.username)==0)
				{
					
					if(strcmp(pres[i*column+3],msg.passwd)==0)
					{
						strcpy(msg.recvmsg,"账号登陆成功");
						break;
					}

					sqlite3_free_table(pres);
					pres = NULL;
					
				}
				else
				{

					strcpy(msg.recvmsg,"账号或密码错误");
				}
			}
					send_ser_msg(newfd,sin,msg);

		}
		break;
	case 1:
		{
			printf("进入case1\n");
			int i = 0;int res=0;
			
			for(i=0;i<(row+1);i++)
			{
			if(strcmp(pres[i*column+2],msg.username)==0)
				{
						strcpy(msg.recvmsg,"该账户已存在");
					sqlite3_free_table(pres);
					pres = NULL;
					res=1;
					break;	
				}
			}
			
			
			if(res==0)
			{
				char buf[512];
				sprintf(buf,"insert into staff_info values ('%d','%d','%s','%s','%d','%s','%s','%s','%s','%d','%lf')",msg.info.no,msg.usertype,msg.username,msg.passwd,msg.info.age,msg.info.phone,msg.info.addr,msg.info.work,msg.info.date,msg.info.level,msg.info.salary);
				char*sql=buf;
				if(sqlite3_exec(db, sql, NULL, &flag, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
					return -1;
				}

				char arr[256];
				sprintf(arr,"注册%s账户",msg.username);
				history(db,arr,msg);
				printf("注册成功\n");
				strcpy(msg.recvmsg,"账户注册成功");
				
			}
				send_ser_msg(newfd,sin,msg);
		}
			break;
		case 2:
			{
			history(db,"删除用户",msg);
			printf("进入case2\n");
			int i = 0;int res=0;
			
			for(i=0;i<(row+1);i++)
			{
				char buf[128]={0};
				sprintf(buf,"%d",msg.info.no);
			if(strcmp(pres[i*column],buf)==0)
				{
						strcpy(msg.recvmsg,"该账户存在");
					sqlite3_free_table(pres);
					pres = NULL;
					res=1;
					break;	
				}
			}
			
			
			if(res==1)
			{
				char buf[512];
				sprintf(buf,"delete from staff_info where no=('%d')",msg.info.no);
				char*sql=buf;
				if(sqlite3_exec(db, sql, NULL, &flag, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
					return -1;
				}
				char arr[256];
				sprintf(arr,"删除工号为%d账户",msg.info.no);
				history(db,arr,msg);

				printf("删除成功\n");
				strcpy(msg.recvmsg,"账户删除成功");

			}
				else
					strcpy(msg.recvmsg,"没有当前账户");
				send_ser_msg(newfd,sin,msg);
	
			}
			break;
		case 3:
			{
		printf("进入case3\n");
			int i = 0;int res=0;
			
			for(i=0;i<(row+1);i++)
			{
				char buf[128]={0};
				sprintf(buf,"%d",msg.info.no);
			if(strcmp(pres[i*column],buf)==0)
				{
					res=1;
					break;	
				}
			}
			
			
			if(res==1)
			{
				char buf[512];
				char info[20]={0};
				switch(msg.flags)
				{
				case 1:
					strcpy(info,"no");
					break;
				case 2:
					strcpy(info,"usertype");
					break;
				case 3:
					strcpy(info,"passwd");
					break;
				case 4:
					strcpy(info,"age");
					break;
				case 5:
					strcpy(info,"phone");
					
					break;
				case 6:
					strcpy(info,"addr");
					break;
				case 7:
					strcpy(info,"work");
					break;
				case 8:
					strcpy(info,"date");
					break;
				case 9:
					strcpy(info,"level");
					break;
				case 0:
					strcpy(info,"salary");
					break;
					
					

				}
				sprintf(buf,"update staff_info set '%s'='%s' where no='%d'",info,msg.recvmsg,msg.info.no);
				char*sql=buf;
				if(sqlite3_exec(db, sql, NULL, &flag, &errmsg) != SQLITE_OK)
				{
					fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
					return -1;
				}
				char arr[256];
				sprintf(arr,"修改%s账户%s为%s",msg.username,info,msg.recvmsg);
				history(db,arr,msg);

				printf("修改成功\n");
				strcpy(msg.recvmsg,"信息修改成功");

			}
				else
					strcpy(msg.recvmsg,"没有当前账户");
				send_ser_msg(newfd,sin,msg);

			}
		break;
		case 4:
		{

			printf("进入case4\n");
			int i = 0;int res=0;
			printf("flags=%d\n",msg.flags);
			if(msg.flags==2)
			{
				msg.flags=row;
			for(i=0;i<(row+1);i++)
			{
				msg.flags--;
				printf("%d\n",row);
				char buf[128];
					sprintf(buf,"%s %s %s %s %s %s %s",pres[i*column],pres[i*column+4],pres[i*column+5],pres[i*column+6],pres[i*column+7],pres[i*column+8],pres[i*column+9]);
					
					printf("查询成功\n");
				char arr[256];
				sprintf(arr,"查询所有账户");
				history(db,arr,msg);
					strcpy(msg.recvmsg,buf);
				send_ser_msg(newfd,sin,msg);
			}
			}
			else if(msg.flags==1)
			{
			for(i=0;i<(row+1);i++)
			{
				char buf[128]={0};
				sprintf(buf,"%d",msg.info.no);
				if(strcmp(pres[i*column],buf)==0)
				{
					printf("查到该账号%s\n",buf);
					strcpy(msg.recvmsg,"该账户存在");	

					char buf[128];
					sprintf(buf,"%s %s %s %s %s %s %s",pres[i*column],pres[i*column+4],pres[i*column+5],pres[i*column+6],pres[i*column+7],pres[i*column+8],pres[i*column+9]);

				char arr[256];
				sprintf(arr,"查询工号为%d的账户",msg.info.no);
				history(db,arr,msg);
					printf("查询成功\n");
					strcpy(msg.recvmsg,buf);
					break;

				}
				else
					strcpy(msg.recvmsg,"没有当前账户");
			}
			}
				send_ser_msg(newfd,sin,msg);
		}
		break;
		case 5:
		{
			char sql[128] = "select *  from ";
			strcat(sql,TABLE2);
			char ** pres = NULL;    //存储查询结果的首地址
			int row, column;        //查询结果的行列数
			char* errmsg = NULL;

			if(sqlite3_get_table(db, sql, &pres, &row, &column, &errmsg) != SQLITE_OK)
			{
				fprintf(stderr, "__%d__ sqlite3_get_table:%s\n", __LINE__, errmsg);
				return -1;
			}
			msg.flags=row;
			for(int i=0;i<(row+1);i++)
			{
			msg.flags--;
				printf("%d\n",row);
				char buf[128];
					sprintf(buf,"%s %s %s",pres[i*column],pres[i*column+1],pres[i*column+2]);					
					strcpy(msg.recvmsg,buf);
				send_ser_msg(newfd,sin,msg);
					
			}
		}
			break;
		case 6:
			{

				printf("进入case6\n");
				int i = 0;int res=0;

				for(i=0;i<(row+1);i++)
				{
					if(strcmp(pres[i*column+2],msg.username)==0)
					{
						res=1;
						break;	
					}
				}


				if(res==1)
				{
					char buf[512];
					char info[20]={0};
					switch(msg.flags)
					{
					case 1:
						strcpy(info,"passwd");
						break;
					case 2:
						strcpy(info,"age");
						break;
					case 3:
						strcpy(info,"phone");

						break;
					case 4:
						strcpy(info,"addr");
						break;



					}
					sprintf(buf,"update staff_info set '%s'='%s' where name='%s'",info,msg.recvmsg,msg.username);
					char*sql=buf;
					printf("%s\n",buf);
					if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
					{
						fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg);
						return -1;
					}
					char arr[256];
					sprintf(arr,"修改%s账户%s为%s",msg.username,info,msg.recvmsg);
					history(db,arr,msg);

					printf("修改成功\n");
					strcpy(msg.recvmsg,"信息修改成功");

				}
				else
					strcpy(msg.recvmsg,"没有当前账户");
				send_ser_msg(newfd,sin,msg);

			}
		break;
		case 7:
		{
			for(int i=0;i<(row+1);i++)
			{
				char buf[128]={0};
				if(strcmp(pres[i*column+2],msg.username)==0)
				{
					strcpy(msg.recvmsg,"该账户存在");	

					char buf[128];
					sprintf(buf,"%s %s %s %s %s %s %s",pres[i*column],pres[i*column+4],pres[i*column+5],pres[i*column+6],pres[i*column+7],pres[i*column+8],pres[i*column+9]);

					printf("%s\n",buf);
				char arr[256];
				sprintf(arr,"查询%s的账户",msg.username);
				history(db,arr,msg);
					printf("查询成功\n");
					strcpy(msg.recvmsg,buf);
					break;

				}
				else
					strcpy(msg.recvmsg,"没有当前账户");
			}
				send_ser_msg(newfd,sin,msg);
			}
			break;
		case 9:
			{
				char arr[256];
				sprintf(arr,"%s账户退出",msg.username);
				history(db,arr,msg);
				exit(0);
				
			}
			break;
			
	}
    //释放获取到的空间
    sqlite3_free_table(pres);
    pres = NULL;
    return 0;
}
int history(sqlite3 *db,char*beheivor,MSG msg)

{
	//创建一个表格存储历史记录
	char* sq2 = "create table if not exists history (name char,time char primary key,words char);" ;
	char* errmsg2 = NULL;

	if(sqlite3_exec(db, sq2, NULL, NULL, &errmsg2) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg2);
		return -1;
	}
	time_t t=time(NULL);
	struct tm*info=NULL;
	info=localtime(&t);
	char time[256];
	sprintf(time,"%d-%02d-%02d %02d:%02d:%02d",info->tm_year+1900,info->tm_mon+1,info->tm_mday,info->tm_hour,info->tm_min,info->tm_sec);
	char words[512];
	sprintf(words,"%s用户在%s进行了%s操作",msg.username,time,beheivor);
	char buf[1024];
	sprintf(buf,"insert into history values ('%s', '%s', '%s')",msg.username,time,words);
	char*sql=buf;
	printf("%s\n",buf);
	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg2) != SQLITE_OK)
	{
		fprintf(stderr, "__%d__ sqlite3_exec:%s\n", __LINE__, errmsg2);
		return -1;

	}
	return 0;
}

Makefile

all:
	gcc server.c -o server -lpthread -lsqlite3
	gcc client.c -o client

clean:
	rm server client

客户端

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


//打印错误新的宏函数
#define ERR_MSG(msg)  do{\
    fprintf(stderr, " __%d__ ", __LINE__);\
    perror(msg);\
}while(0)
#define ADMIN 0	//管理员
#define USER  1	//用户

#define NAMELEN 16
#define DATALEN 128
/*员工基本信息*/
typedef struct staff_info{
	int  no; 			//员工编号
	int  usertype;  	//ADMIN 1	USER 2	 
	char name[NAMELEN];	//姓名
	char passwd[8]; 	//密码
	int  age; 			// 年龄
	char phone[NAMELEN];//电话
	char addr[DATALEN]; // 地址
	char work[DATALEN]; //职位
	char date[DATALEN];	//入职年月
	int level;			// 等级
	double salary ;		// 工资
	
}staff_info_t;

/*定义双方通信的结构体信息*/
typedef struct {
	int  msgtype;     //请求的消息类型
	int  usertype;    //ADMIN 1	USER 2	   
	char username[NAMELEN];  //姓名
	char passwd[8];			 //登陆密码
	char recvmsg[DATALEN];   //通信的消息
	int  flags;      //标志位
	staff_info_t info;      //员工信息
}MSG;
//指定要连接的服务器的地址信息
//#define PORT 6666               //1024~49151                       
//#define IP  "192.168.31.199"    //本机IP,用ifconfig查看
int rcv_cli_msg(int sfd,MSG *msg,struct sockaddr_in sin);
int send_cli_msg(int sfd,MSG msg,struct sockaddr_in sin);
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");


	//绑定客户端的地址信息结构体--》非必须绑定 
	
	//填充要连接的服务器的地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family 		= AF_INET;
	sin.sin_port 		= htons(*(int*)argv[2]);
	sin.sin_addr.s_addr = inet_addr(argv[1]);

	//连接服务器 connect
	if(connect(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
	{
		ERR_MSG("connect");
		return -1;
	}
	MSG msg={0};
	char choose=0;
	//选择用户登陆模式
	

DENGLU:
		printf("-----请选择用户登陆模式----\n");
		printf("-----1、管理员模式登陆-----\n");
		printf("-----2、普通用户模式登陆---\n");
		choose=getchar();	
		while(getchar()!=10);
	if(choose=='2')
	{
		bzero(&msg,sizeof(msg));
		msg.msgtype=0;
		msg.usertype=2;
		printf("输入用户账号\n");
		scanf("%s",msg.username);
		printf("输入用户密码\n");
		scanf("%s",msg.passwd);
		send_cli_msg(sfd,msg,sin);
		printf("%s",msg.username);
		rcv_cli_msg(sfd,&msg,sin);
		//recv(sfd,&msg,sizeof(msg),0);
		if(strcmp(msg.recvmsg,"账号登陆成功"))
		{
			printf("%s\n",msg.recvmsg);
			goto DENGLU;
		}
		printf("%s\n",msg.recvmsg);
		while(1)
		{
			//system("clear");
			printf("---------------------------\n");
			printf("--------1. 修改数据--------\n");
			printf("--------2. 查询用户--------\n");
			printf("--------3.退出-------------\n");
			printf("---------------------------\n");

			while(getchar()!=10);
			printf("请输入选项>>>");
			//scanf("%c",&choose);
			choose=getchar();
			while(getchar()!=10);
			switch(choose)
			{
			case'1':
					{

						msg.msgtype=6;
						printf("选择需要修改的数据:\n");
						printf("---------------------------\n");
						printf("--------1. 员工密码--------\n");
						printf("--------2. 员工年龄--------\n");
						printf("--------3. 员工电话--------\n");
						printf("--------4. 员工地址--------\n");
						scanf("%d",&msg.flags);
						while(getchar()!=10);
						printf("输入想要修改的值\n");
						scanf("%s",msg.recvmsg);
					}
					send_cli_msg(sfd,msg,sin);
					rcv_cli_msg(sfd,&msg,sin);
					printf("%s\n",msg.recvmsg);


					break;
			case'2':
					{
						msg.msgtype=7;
						int flag=0;
						msg.flags=1;
						send_cli_msg(sfd,msg,sin);
						rcv_cli_msg(sfd,&msg,sin);
						printf("%s\n",msg.recvmsg);

					}
					break;
			case'3':
					{
						exit(0);
					}
			}



}
}

	if(choose=='1')
	{
		bzero(&msg,sizeof(msg));
		msg.msgtype=0;
		msg.usertype=1;
		printf("输入管理员账号\n");
		scanf("%s",msg.username);
		printf("输入管理员密码\n");
		scanf("%s",msg.passwd);
		send_cli_msg(sfd,msg,sin);
		printf("%s\t%s",msg.username,msg.passwd);
		rcv_cli_msg(sfd,&msg,sin);
		//recv(sfd,&msg,sizeof(msg),0);
		if(strcmp(msg.recvmsg,"账号登陆成功"))
		{
			printf("%s\n",msg.recvmsg);
			goto DENGLU;
		}
		printf("%s\n",msg.recvmsg);

		while(1)
		{
			//char a;
			//scanf("%c",&a);
			//system("clear");
			printf("---------------------------\n");
			printf("--------1. 添加用户--------\n");
			printf("--------2. 删除用户--------\n");
			printf("--------3. 修改数据--------\n");
			printf("--------4. 查询用户--------\n");
			printf("--------5. 历史记录--------\n");
			printf("--------0.退出-------------\n");
			printf("---------------------------\n");

			while(getchar()!=10);
			printf("请输入选项>>>");
			//scanf("%c",&choose);
			choose=getchar();
			while(getchar()!=10);
			switch(choose)
			{
				case '1':
					{
						msg.msgtype=1;
						printf("输入需要添加的用户类型\n");
						scanf("%d",&msg.usertype);
						printf("输入需要添加的工号\n");
						scanf("%d",&msg.info.no);
						printf("输入需要添加的用户账号\n");
						scanf("%s",msg.username);
						printf("输入需要添加的用户密码\n");
						scanf("%s",msg.passwd);
						send_cli_msg(sfd,msg,sin);
						rcv_cli_msg(sfd,&msg,sin);
						printf("%s\n",msg.recvmsg);


					}
					break;
				case'2':
					{
						msg.msgtype=2;
						printf("输入需要删除的用户工号\n");
						scanf("%d",&msg.info.no);
						send_cli_msg(sfd,msg,sin);
						rcv_cli_msg(sfd,&msg,sin);
						printf("%s\n",msg.recvmsg);
						
						
					}
					break;
				case'3':
					{

						msg.msgtype=3;
						printf("输入需要修改的用户工号\n");
						scanf("%d",&msg.info.no);
						printf("选择需要修改的数据:\n");
						printf("---------------------------\n");
						printf("--------1. 员工编号--------\n");
						printf("--------2. 员工权限--------\n");
						printf("--------3. 员工密码--------\n");
						printf("--------4. 员工年龄--------\n");
						printf("--------5. 员工电话--------\n");
						printf("--------6. 员工地址--------\n");
						printf("--------7. 员工职位--------\n");
						printf("--------8. 入值年月--------\n");
						printf("--------9. 员工等级--------\n");
						printf("--------0. 员工工资--------\n");
						scanf("%d",&msg.flags);
						while(getchar()!=10);
						printf("输入想要修改的值\n");
						scanf("%s",msg.recvmsg);
					}
					send_cli_msg(sfd,msg,sin);
					rcv_cli_msg(sfd,&msg,sin);
					printf("%s\n",msg.recvmsg);


					break;
					
				case '4':
			{
				int flag=0;
				msg.msgtype=4;
				msg.flags=0;
				printf("选择要查询的内容:1、按工号查询,2、查看总表\n");
				scanf("%d",&flag);
				if(flag==1)
				{
						msg.flags=1;
						printf("输入需要查询的用户工号\n");
						scanf("%d",&msg.info.no);
						send_cli_msg(sfd,msg,sin);
						rcv_cli_msg(sfd,&msg,sin);
						printf("%s\n",msg.recvmsg);
				}
				if(flag==2)
				{
					msg.flags=2;
					send_cli_msg(sfd,msg,sin);
					printf("%d\n",msg.flags);
					while(msg.flags!=0)
					{
						rcv_cli_msg(sfd,&msg,sin);
						printf("%s\n",msg.recvmsg);

						
					}
				}
			}
			break;
				case '5':
			{
				printf("进入case5\n");
				msg.msgtype=5;
				send_cli_msg(sfd,msg,sin);
					rcv_cli_msg(sfd,&msg,sin);
					printf("第一次recv成功\n");
					printf("%d\n",msg.flags);
					while(msg.flags>0)
					{
						rcv_cli_msg(sfd,&msg,sin);	
						printf("%s\n",msg.recvmsg);
					}	
				
			}
				break;

				case'0':
				{
					msg.msgtype=9;
				send_cli_msg(sfd,msg,sin);

					exit(0);
				}
				break;
			}
		}
			//rcv_cli_msg(sfd,&msg,sin);

	}
	//关闭套接字
	close(sfd);

	return 0;
}
int send_cli_msg(int sfd,MSG msg,struct sockaddr_in sin)
{
	
	ssize_t res = 0;
		//发送

		if(send(sfd,&msg, sizeof(msg), 0) < 0)
		{
			ERR_MSG("send");
			return -1;
		}
		printf("send success\n");
		return 0;
}
int rcv_cli_msg(int sfd,MSG *msg,struct sockaddr_in sin)
{
		//接收 
		ssize_t res=0;
		bzero(msg, sizeof(msg));
		//printf("清空msg\n");
		res = recv(sfd,msg, sizeof(MSG), 0);
		if(res < 0)
		{
			ERR_MSG("recv");
			return -1;
		}
		else if(0 == res)
		{
			printf("server is off-line\n");
			
		}
	//	printf("%s\n", msg->recvmsg);
	

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值