欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-22 12:25:28
...

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

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

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

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

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

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


服务器端

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

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

(1) 打开服务器:

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

(2) 收到客户端数据:

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

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

员工客户端

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

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

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

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

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

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

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

源代码

服务器

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
#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 <ip> <port>\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 <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#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 aaa@qq.com

client:client.o
	$(CC) $< -o aaa@qq.com

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

.PHONY:
	clean

clean:
	rm *.o server client

服务器

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

客户端1

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

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

客户端2

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

下载

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

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