Linux多线程编程之员工信息管理系统

       员工信息管理系统是基于Linux 多线程并发服务器编程,由服务器端和客户端构成,客户端可以运行在多个不同的主机上连接服务器,服务器对员工信息的操作结果通过“员工信息文件”来保存,即:“员工信息”存放在后台的文件中,相当于数据库。当用户登录后,根据用户名判断用户是否为管理员。如果为管理员,则进入管理员目录,如果为普通员工,则进入员工目录。在管理员目录,可以查看任意员工的信息,还可修改员工的信息,包括工资、评级,添加或删除用户。在员工目录,可以查看自己的信息,不能查看其他人的信息,可以修改自己的电话,地址等个人信息,但不能修改工资等管理员权限信息。

Linux多线程编程之员工信息管理系统_第1张图片

       员工信息管理系统采用TCP协议,将在客户端采集的信息打包成结构体MSG,将MSG传送到服务器,服务器通过对MSG的解析,执行相关的操作,并把客户端请求的数据打包成结构体MSG发送给客户端,实现员工信息的管理。

(1) 客户端模块,通过对用户名的判断,判断用户是否为管理员,从而提供不同的接口,并将用户的请求打包为MSG结构体,发送给服务器。采用统一的结构体MSG在服务器与客户端进行信息交流,可以统一接口,方便信息分析。

(2)服务器模块,通过对结构体MSG的分析,对客户端的请求新建子进程来处理客户端的请求,实现多用户。

Linux多线程编程之员工信息管理系统_第2张图片


服务器端

服务器端是员工和管理员的数据信息存储区。服务器负责通过判断客户端一系列请求,对数据做出相应的操作。

主要包含服务器通讯模块、服务器数据库处理模块。服务器端功能描述如下:

(1) 打开服务器:

打开服务器时,打开数据文件和网络通讯,并对网络进行监听。

(2) 收到客户端数据:

从服务器接受到数据后先判断登陆结构体是否有变化,如果有变化,表示有新用户登陆,则创建一个子进程,如果没有变化则表示无用户登陆或收到数据为已登录用户的数据。如果是用户登陆,则判断是否是管理员账户。通过接受客户端请求操作数据文件,完成后将结果发送给客户端,并返回等待下次的数据到来,如果出现错误,则发送错误信息给客户端。

Linux多线程编程之员工信息管理系统_第3张图片

员工客户端

员工和管理员通过客户端登陆后执行操作。不同的是在通过姓名验证的时候,系统会自动判断登陆者身份,以辨认是普通用户还是系统管理员。通过不同类别用户的登录从而实现不同的操作。普通用户有如下操作:查看和修改自身的信息。系统管理员有如下操作:查看所有用户信息及对用户信息的增,删,改,查。用户信息根据用户需求设定,初步设计包含员工编号,用户名,联系电话,住址,年龄,工资情况,员工评级七项。其中工资情况和员工评级为只有管理员权限可修改项。

客户端主要包括用户登录模块、用户权限选择模块、用户信息的操作请求模块和退出程序几部分。

(1)登录模块:连接上服务器之后进入登录模块,提示用户输入用户名和密码。如果用户名和密码正确则登录成功进入相应的界面,否则返回登录界面。

(2)用户权限选择模块:用户登录成功之后,经过服务器端判断决定用户进入对应权限的界面。

(3)用户信息操作模块:如果进入的是管理员界面则管理员过姓名选择相应的员工信息后,具有添加用户、删除用户、修改用户信息、查询用户信息四项权限。如果进入的时普通用户界面则该用户仅具有修改个人信息(包含修改密码)、查询用户信息两项权限。向服务器发送相应的请求,实现功能。

(4)退出程序:当用户操作结束之后退出程序,也可返回上一层目录。

Linux多线程编程之员工信息管理系统_第4张图片

源代码

服务器

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "head.h"

typedef struct sockaddr SA;
int     Info_rmark = 0;//文件Info.text互斥操作的读
int     Info_wmark = 0;//文件Info.text互斥操作的写
int     User_rmark = 0;//文件User.text互斥操作的读
int     User_wmark = 0;//文件User.text互斥操作的写

void findMsg(MSG *);
void findUser(MSG *);
void addMsg(MSG *);
void addUser(MSG *);
void delMsg(MSG *);
void delUser(MSG *);


void* handler(void * arg)//接收客户端消息,判断消息类型
{
	MSG  msg;
	int n;
	int connfd = (int)arg;
	while(1)
	{
		n = recv(connfd,&msg, sizeof(MSG), 0);
		printf("get message from %s   type:%d  sign:%d\n",msg.name,msg.type,msg.sign);
		if(msg.type == QUIT)
		{
			printf("user %s quit!\n",msg.name);
			pthread_exit(NULL);
			close(connfd);
		}
		if(n == -1)
			break;
		if(msg.type == QUIT)
			break;
		getMsg(&msg);//取得客户端先要的信息,或者修改信息
		printf("send message to %s    type:%d   sign:%d\n\n",msg.name,msg.type,msg.sign);
		send(connfd,&msg, sizeof(MSG), 0);
	}

	close(connfd);
	pthread_exit(NULL);

}
int main(int argc, const char *argv[])//./server 127.0.0.1 10001
{
#if 0 
	USER user;
	strcpy(user.name,"zx");
	strcpy(user.passwd,"123");
	user.type = 11;
	user.no = 100;

	FILE * fp = fopen("./user.dat","wb");
	fwrite(&(user),sizeof(USER),1,fp);//写文件
	fclose(fp);
#endif

	int listenfd, connfd;
	
	struct sockaddr_in ser_addr, cli_addr;

	if(argc != 3)
	{
		printf("plz input %s  \n", argv[0]);
		exit(-1);
	}

	if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket");
		exit(-1);
	}

	bzero(&ser_addr, sizeof(ser_addr));
	ser_addr.sin_family = AF_INET;
	ser_addr.sin_port = htons(atoi(argv[2]));//"10001"
	ser_addr.sin_addr.s_addr = inet_addr(argv[1]);

	if(bind(listenfd, (SA *)&ser_addr, sizeof(ser_addr)) == -1)
	{
		perror("bind");
		exit(-1);
	}

	listen(listenfd, 5);

	bzero(&cli_addr, sizeof(cli_addr));
	socklen_t len = sizeof(cli_addr);
	printf("listenfd = %d\n", listenfd);


	while(1)//接受客户端请求,创建子线程
	{
		if((connfd = accept(listenfd, (SA *)&cli_addr, &len)) == -1)
		{
			perror("accept");
			exit(-1);
		}
		printf("connect with ip : %s, port : %d\n", 
				inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
		/*父进程接收客户端请求后,创建子进程与客户端通信*/

		pthread_t child_pthread;

		if(pthread_create(&child_pthread,NULL,handler,(void *)connfd) < 0)
		{
			perror("pthread_create");
			exit(1);
		}
	}

	close(listenfd);
	return 0;
}

int getMsg(MSG * msg)//判断消息类型操作
{
	switch(msg->type)
	{
	case READ:
		findMsg(msg);
		break;
	case CHANGE:
		delUser(msg);
		addUser(msg);
		delMsg(msg);
		addMsg(msg);
		break;
	case ADD:
		addUser(msg);
		addMsg(msg);
		break;
	case DELETE:
		delUser(msg);
		delMsg(msg);
		break;
	case LOAD:
		findUser(msg);
		break;
	default:
		break;		
	}
	return 0;
}

void findMsg(MSG *msg)//查找信息操作
{
	INFO info_temp;
	int flag = 0;
	FILE *fp;
 
	while(Info_wmark > 0) //实现读写文件的互斥
	{
		usleep(100000);
	}
	Info_rmark++;

	if((fp = fopen("./info.dat","rb")) == NULL)
	{
		printf("User %s requset:no file info.dat\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}


	if(strcmp(msg->info.name,"null") != 0)//姓名不为空
	{
		while(fread(&info_temp,sizeof(INFO),1,fp) != 0)//读文件
		{
			if(strcmp(info_temp.name,msg->info.name) == 0)//比较名字是否相同
			{
				if(flag == 1)
				{
					if((msg->info.no != 0)&&(msg->info.no == info_temp.no))
					{//存在另个名字一样的员工,则进行编号的对比
					//如果一样则成功返回
						msg->info = info_temp;
						msg->sign = SUCCESS;
		    			strcpy(msg->data,"find it");
						return;
					}
					else
					{
						continue;//若编号不同则保留上一个员工信息
					}
				}
				msg->sign = SUCCESS;
				strcpy(msg->data,"find it");
				msg->info = info_temp;
				flag = 1;
			}

		}
		if(flag == 0)
		{
			msg->sign = FAILED;
		    strcpy(msg->data,"not find");
			return;
		}


	}
	else if(msg->info.no != 0)
	{
		while(fread(&info_temp,sizeof(INFO),1,fp) != 0)//读文件
		{
			if(info_temp.no == msg->info.no)//比较编号是否相同
			{
				if(flag == 1)
				{
					if((strcmp(msg->info.name,"null") != 0)&&(strcmp(msg->info.name,info_temp.name) == 0))
					{//存在另个编号一样的员工,则进行姓名的对比
						msg->info = info_temp;
						msg->sign = SUCCESS;
		    			strcpy(msg->data,"find it");
						return;
					}
					else
					{
						continue;//若姓名不同则保留上一个员工信息
					}
				}
				msg->info = info_temp;
				flag = 1;
			}

		}
		if(flag == 0)
		{
			msg->sign = FAILED;
			strcpy(msg->data,"not find");
			return;
		}

	}

	fclose(fp);
	Info_rmark--;

}
void addMsg(MSG *msg)//添加信息操作
{
	FILE * fp;
	while((Info_wmark > 0)&&(Info_rmark > 0)) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	Info_wmark++;

	if((fp = fopen("./info.dat","ab")) == NULL)
	{
		printf("User %s requset:open Info.text failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}

	fwrite(&(msg->info),sizeof(INFO),1,fp) ;//写文件

	printf("add info for %s ok!\n",msg->name);

	msg->sign = SUCCESS;
	strcpy(msg->data,"write info ok!\n");

	fclose(fp);
	Info_wmark--;
}
void delMsg(MSG *msg)//删除信息操作
{
	FILE * fp;
	int i = 0;
	INFO  info_temp[N];

	while(Info_wmark > 0) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	Info_rmark++;

	if((fp = fopen("./info.dat","rb")) == NULL)
	{
		printf("User %s requset:open info.dat failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}

	while(fread(&(info_temp[i++]),sizeof(INFO),1,fp) != 0)//读文件
	{
		;
	}
	fclose(fp);
	Info_rmark--;
	//向文件中写数据
	while((Info_wmark > 0)&&(Info_rmark > 0)) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	Info_wmark++;

	if((fp = fopen("./info.dat","wb")) == NULL)
	{
		printf("User %s requset:open info.dat failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}
	while(i--)
	{
		if(msg->info.no == info_temp[i].no)
			continue;
		fwrite(&(info_temp[i]),sizeof(INFO),1,fp);//写文件
	}


	printf("delete info for %s ok!\n",msg->name);

	msg->sign = SUCCESS;
	strcpy(msg->data,"change info ok!\n");

	fclose(fp);
	Info_wmark--;
}
void delUser(MSG *msg)//删除用户操作
{
	FILE * fp;
	int i = 0;
	USER user_temp[N];

	while(User_wmark > 0) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	User_rmark++;

	if((fp = fopen("./user.dat","rb")) == NULL)
	{
		printf("User %s requset:open user.dat failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}
	while(fread(&(user_temp[i++]),sizeof(USER),1,fp) != 0)//读文件
	{
		;
	}
	fclose(fp);
	User_rmark--;

	//向文件中写数据
	while((User_wmark > 0)&&(User_rmark > 0)) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	User_wmark++;

	if((fp = fopen("./user.dat","wb")) == NULL)
	{
		printf("User %s requset:open user.dat failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}
	while(i--)
	{
		if(msg->info.no != user_temp[i].no)
			fwrite(&(user_temp[i]),sizeof(USER),1,fp);//写文件
	}

	msg->sign = SUCCESS;

	printf("delete user for %s  ok !\n",msg->name);

	strcpy(msg->data,"delete user ok!\n");

	fclose(fp);
	User_wmark--;
	
}
void findUser(MSG *msg)//查找用户操作
{
	FILE * fp;
	int flag = 0;
	while(User_wmark > 0) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	User_rmark++;

	if((fp = fopen("./user.dat","rb")) == NULL)
	{
		printf("User %s requset:no file user.dat\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}

	USER user_temp;

	while(fread(&user_temp,sizeof(USER),1,fp) != 0)//读文件
		{
			if(strcmp(user_temp.name,msg->name) == 0)//比较名字是否相同
			{
				if(strcmp(msg->passwd,user_temp.passwd) == 0)
					{
						flag = 1;
						msg->sign = SUCCESS;
						msg->info.type = user_temp.type;
						msg->sign = SUCCESS;
		    			strcpy(msg->data,"all is right");
						return;
					}
			}

		}
		if(flag == 0)
		{
			msg->sign = FAILED;
		    strcpy(msg->data,"find user failed!\n");
			return;
		}

	fclose(fp);
	User_rmark--;

}
void addUser(MSG *msg)//添加用户操作
{
	FILE * fp;
	USER user;
	strcpy(user.name,msg->info.name);
	strcpy(user.passwd,msg->passwd);
	user.type = STAFF;
	user.no = msg->info.no;

	while((User_wmark > 0)&&(User_rmark > 0)) //实现读与写和读文件的互斥
	{
		usleep(100000);
	}
	User_wmark++;

	if((fp = fopen("./user.dat","ab")) == NULL)
	{
		printf("User %s requset:open user.dat failed\n",msg->name);
		msg->sign = FAILED;
		strcpy(msg->data,"not file");
		return;
	}

	fwrite(&(user),sizeof(USER),1,fp);//写文件

	printf("add user for %s  ok!\n",msg->name);

	msg->sign = SUCCESS;
	strcpy(msg->data,"add user ok!\n");

	fclose(fp);
	User_wmark--;

}

客户端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "client.h"


int main(int argc, const char *argv[])
{
	int sockfd;
	struct sockaddr_in  serveraddr;
	MSG  msg;

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		exit(1);
	}

	bzero(&serveraddr, sizeof(serveraddr));
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(atoi(argv[2]));
	serveraddr.sin_addr.s_addr = inet_addr(argv[1]);

	if(connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
	{
		perror("connect");
		exit(1);
	}

	while(1)
	{
		puts("------------------------------------");
		puts("----------Login ^_^  ^_^-------------");
		puts("------------------------------------");

		/*
		 *  输入登录信息
		 */
		printf("please input your name >");
		fgets(msg.name, N, stdin);
		msg.name[strlen(msg.name) - 1] = '\0';

		printf("please input your password >");
		fgets(msg.passwd, N, stdin);
		msg.passwd[strlen(msg.passwd) - 1] = '\0';
		msg.type = LOAD;


		send(sockfd, &msg, sizeof(MSG), 0);//发送消息给服务器,进行登录验证。
		printf("---load type %d\n", msg.type);
		recv(sockfd, &msg, sizeof(MSG), 0);//接收服务器的反馈消息。

		if(msg.sign ==  FAILED)//登录失败
		{
			printf("%s\n", msg.data);
			continue;
		}

		if(msg.sign == SUCCESS)//登录成功 
		{
			if(msg.info.type == STAFF)
			{
				goto User;//进入普通用户界面
			}
			else if(msg.info.type == ADM)
			{
				goto Admin;// 进入管理员界面 
			}
		}
	}

	/*普通用户界面*/
User:
	while(1)
	{
		/*普通用户权限*/
		puts("----------------------------------------------------");
		puts("-------1: select info 2:modify passwd 3:exit --------");
		puts("-----------------------------------------------------");
		printf("please input you command >");

		/*
		 *输入命令错误处理
		 */
		int command;
		char clear[N];
		if(scanf("%d",&command) == 0)
		{
			fgets(clear, N, stdin);
			continue;
		}

		switch(command)
		{
		case 1:
			msg.type = READ;
			strcpy(msg.info.name , msg.name); 
			msg.info.no = 0;

			send(sockfd, &msg, sizeof(MSG), 0);//发送查询消息
			recv(sockfd, &msg, sizeof(MSG), 0);//接收服务器的反馈消息
			printf(" ---------recv sign %d\n", msg.sign);
			/*打印用户自身信息*/

			printf("姓名    地址                  年龄    级别\n");
			printf("%s %s %d %d \n",msg.info.name, msg.info.addr, msg.info.age, msg.info.level);
			printf("编号    工资    电话      用户类型\n");
			printf("%d %lf %s %d \n",msg.info.no, msg.info.salary, msg.info.phone, msg.info.type);

			break;
		case 2:
			getchar();
			printf("please input your new password >");
			getchar();
			fgets(msg.passwd, N, stdin);
			msg.passwd[strlen(msg.passwd) - 1] = '\0'; 
			msg.type = CHANGE;
			send(sockfd, &msg, sizeof(MSG), 0);//发送修改密码的消息
			break;

		case 3:
			msg.type = QUIT;
			send(sockfd, &msg, sizeof(MSG), 0);
			goto Exit;//退出程序
		}
	}


/*管理员界面*/
Admin:
	while(1)
	{
		/*管理员的权限*/
		puts("--------------------------------------------------------------------");
		puts("-----1:add user 2:delete user  3:modify info 4:select info  5:exit ----");
		puts("---------------------------------------------------------------------");
		printf("please input you command >");//输入对应的操作数字。

		/*输入命令错误处理*/
		int result;
		int command;
		char clear[N];
		if(scanf("%d",&command) == 0)
		{
			fgets(clear, N, stdin);
			continue;
		}

		switch(command)
		{
		case 1:

			/*添加用户*/
			do_adduser(sockfd, &msg);
			if(result == SUCCESS)
			{
				puts("register OK");
			}
			else if(result == FAILED)
			{
				printf("%s\n", msg.data);
				continue;
			}
			break;

		case 2:
			/*删除用户*/
			result = do_deluser(sockfd, &msg);
			if(result == SUCCESS)
			{
				puts("delete OK!");
			}
			else if(result == FAILED)
			{
				printf("%s\n", msg.data);
				puts("failed to delete user");
				continue;
			}
			break;

		case 3:
			/*修改用户信息*/
			result = do_modifyuser(sockfd, &msg);
			if(result == SUCCESS)
			{
				puts("success to modify !");
			}
			else if(result == FAILED)
			{
				printf("%s\n", msg.data);
				puts("failed to modify!");
				continue;
			}
			break;
		case 4:	
			/*查询用户信息*/
			result = do_selectuser( sockfd, &msg);
			if( result == SUCCESS)
			{
				printf("姓名    地址                  年龄    级别\n");
				printf("%s %s %d %d \n",msg.info.name, msg.info.addr, msg.info.age, msg.info.level);
				printf("编号    工资    电话      用户类型\n");
				printf("%d %lf %s %d \n",msg.info.no, msg.info.salary, msg.info.phone, msg.info.type);
			}
			else if( result == FAILED)
			{
				printf("%s\n", msg.data);
				puts("failed to select!");
				continue;
			}
			break;
		case 5:
			msg.type = QUIT;
			send(sockfd, &msg, sizeof(MSG), 0);
			goto Exit;
		}
	}

Exit:
	close(sockfd); //退出时关闭套接字
	return 0;
}


/*添加用户*/
int do_adduser(int sockfd, MSG *msg)
{
	printf("please input username >");
	getchar();//清除垃圾字符
	fgets((msg->info).name, N, stdin);
	(msg->info).name[strlen((msg->info).name) - 1] = '\0'; 

	printf("please input userpasswd >");
	fgets(msg->passwd, N, stdin);
	msg->passwd[strlen(msg->passwd) - 1] = '\0'; 

	printf("please input useraddr >");
	fgets((msg->info).addr, N, stdin);
	(msg->info).addr[strlen((msg->info).addr) - 1] = '\0'; 

	char clear[N];
input_age: 
	printf("please input userage >"); //输入类型不匹配时重新输入
	if(scanf("%d",&(msg->info.age)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);//清理输入垃圾
		goto input_age;
	}
	getchar();

input_level:
	printf("please input userlevel >");
	if(scanf("%d",&(msg->info.level)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_level;
	}
	getchar();

input_usrno:
	printf("please input userno >");
	if(scanf("%d",&(msg->info.no)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_usrno;
	}
	getchar();

input_salary:
	printf("please input usersalary >");
	if(scanf("%lf",&(msg->info.salary)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_salary;
	}
	getchar();

	printf("please input userphone >");
	fgets((msg->info).phone, N, stdin);
	(msg->info).phone[strlen((msg->info).phone) - 1 ] = '\0';

input_usertype:
	printf("please input usertype >");
	if(scanf("%d", &(msg->info.type)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_usertype;
	}
	getchar();

	msg->type = ADD;//发送个服务器的操作类型

	/*
	 * 发送给服务器的结构体类型
	 * 必须和客户端的一致。
	 */
	send(sockfd, msg, sizeof(MSG), 0);
	recv(sockfd, msg, sizeof(MSG), 0);

	return msg->sign;// 返回服务器端的处理信息。

}

/*删除用户*/
int do_deluser(int sockfd, MSG *msg)
{
	printf("please input username >");
	getchar();
	fgets((msg->info).name, N, stdin);
	(msg->info).name[strlen((msg->info).name) - 1] = '\0'; 

	printf("please input userno >");
	if(scanf("%d", &(msg->info.no)) == 0)
	{
		msg->info.no = 0;
	}

	msg->type =  DELETE;
	send(sockfd, msg, sizeof(MSG) , 0);
	recv(sockfd, msg, sizeof(MSG) , 0);

	return msg->sign;// 返回服务器端的处理信息。
}

/*查询用户信息*/
int do_selectuser(int sockfd, MSG *msg)
{
	printf("please input username >");
	getchar();
	fgets((msg->info).name, N, stdin);
	(msg->info).name[strlen((msg->info).name) - 1] = '\0'; 

	/*
	 * 当输入其他字符时,默认要查询的no的值为0。
	 */
	printf("please input userno >");
	if(scanf("%d", &(msg->info.no)) == 0)
	{
		msg->info.no = 0;
	}
	msg->type =  READ;//发送给服务器的操作类型。 
	send(sockfd, msg, sizeof(MSG) , 0);
	recv(sockfd, msg, sizeof(MSG) , 0);

	return msg->sign;// 返回服务器端的处理信息。
}

/*修改用户信息*/
int do_modifyuser(int sockfd, MSG *msg)
{
	printf("please input username >");
	getchar();
	fgets((msg->info).name, N, stdin);
	(msg->info).name[strlen((msg->info).name) - 1] = '\0'; 

	printf("please input userpasswd >");
	fgets(msg->passwd, N, stdin);
	msg->passwd[strlen(msg->passwd) - 1] = '\0'; 

	printf("please input useraddr >");
	fgets((msg->info).addr, N, stdin);
	(msg->info).addr[strlen((msg->info).addr) - 1] = '\0'; 

	char clear[N];
input_age: 
	printf("please input userage >");
	if(scanf("%d",&(msg->info.age)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_age;
	}
	getchar();

input_level:
	printf("please input userlevel >");
	if(scanf("%d",&(msg->info.level)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_level;
	}
	getchar();

input_usrno:
	printf("please input userno >");
	if(scanf("%d",&(msg->info.no)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_usrno;
	}
	getchar();

input_salary:
	printf("please input usersalary >");
	if(scanf("%lf",&(msg->info.salary)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_salary;
	}
	getchar();

	printf("please input userphone >");
	fgets((msg->info).phone, N, stdin);
	(msg->info).phone[strlen((msg->info).phone) - 1 ] = '\0';

input_usertype:
	printf("please input usertype >");
	if(scanf("%d", &(msg->info.type)) == 0)
	{
		printf("the type error!\n");
		fgets(clear, N, stdin);
		goto input_usertype;
	}
	getchar();

	msg->type = CHANGE;
	send(sockfd, msg, sizeof(MSG), 0);
	recv(sockfd, msg, sizeof(MSG), 0);

	return msg->sign;// 返回服务器端的处理信息。
}

运行结果

操作步骤

(1)执行命令gcc server.c -o server -lpthread生成可执行文件server。

(2)执行命令./server 127.0.0.1 10001,运行服务器端。

(3)执行命令gcc client.c -o client -lpthread生成可执行文件client。

(4)执行命令./client 127.0.0.1 10001,模拟客户1。

(5)执行命令./client 127.0.0.1 10001,模拟客户2。

(6)在客户端按下Ctrl+C,关闭客户连接。

当然也可写成Makefile文件直接编译

CC=gcc
CFLAGS=-Wall -g -O2 -lpthread

all:server client

server:server.o
	$(CC) $< -o $@

client:client.o
	$(CC) $< -o $@

%*.o:%*.c
	$(CC) $(CFLAGS) $< -o $@

.PHONY:
	clean

clean:
	rm *.o server client

服务器

Linux多线程编程之员工信息管理系统_第5张图片

客户端1

Linux多线程编程之员工信息管理系统_第6张图片

Linux多线程编程之员工信息管理系统_第7张图片

客户端2

Linux多线程编程之员工信息管理系统_第8张图片

下载

基于Linux的员工信息管理系统

http://download.csdn.net/download/u010872301/10049611

你可能感兴趣的:(Userspace开发)