项目管理系统

news2024/12/27 11:35:07

项目要求

1)服务器负责管理所有员工表单(以数据库形式),其他客户端可通过网络连接服务器来查询员工表单。

2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。

3)管理员账号可以查看、修改、添加、删除员工信息,同时具有查询历史记录功能,管理员要负责管理所有的普通用户。

4)普通用户只能查询修改与本人有关的相关信息,其他员工信息不得查看修改。

5)服务器能同时相应多台客户端的请求功能。并发

项目涉及的知识点

1.TCP通信的服务器、客户端编程流程

        1.服务器:

                1)创建套接字

                2)绑定ip和端口号

                3)监听

                4)等待客户端连接

        2.客户端:

                1)创建套接字

                2)连接服务器

2.服务器并发

        1)多线程

        2)多进程

        3)IO多路复用:select

3.sqlite3数据库常用语句以及编程接口

        编译数据库接口相关c文件需要链接库 -lsqlite3

项目流程图

服务器

客户端

通信结构体的构建

/*员工基本信息*/
typedef struct staff_info{
    int  no;             //员工编号
    int  usertype;      //ADMIN 0    USER 1     
    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 0    USER 1       
    char username[NAMELEN];  //姓名
    char passwd[8];             //登陆密码
    char recvmsg[DATALEN];   //通信的消息
    int  flags;      //标志位
    void *released;
 staff_info_t info;      //员工信息
}MSG;

代码

头文件

 
#ifndef _COMMON_H_
#define _COMMON_H_
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sqlite3.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <pthread.h>
 
#define STAFF_DATABASE 	 "staff_manage_system.db"
 
#define USER_LOGIN 		0x00000000  // login	登陆    0x00000001
#define USER_MODIFY 	0x00000001  // user-modification  修改
#define USER_QUERY 		0x00000002  // user-query   查询
 
#define ADMIN_LOGIN 	0x10000000  // login	         登陆    0x00000001
#define ADMIN_MODIFY 	0x10000001 // admin_modification 修改
#define ADMIN_ADDUSER 	0x10000002 // admin_adduser      添加
#define ADMIN_DELUSER 	0x10000004 // admin_deluser      删除
#define ADMIN_QUERY 	0x10000008  //hitory_query       查找
#define ADMIN_HISTORY 	0x10000010  //hitory_history     历史
 
#define ADMIN_LIST      0x10000011 //列表
 
#define QUIT 			0x11111111
 
#define ADMIN 0	//管理员
#define USER  1	//用户
 
#define PASSLEN 8
#define NAMELEN 16
#define DATALEN 128
 
/*员工基本信息*/
typedef struct staff_info
{
	int  no; 					//员工编号
	int  usertype;  			//ADMIN 1	USER 2	 
	char name[NAMELEN];			//姓名
	char passwd[PASSLEN]; 		//密码
	int  age; 					// 年龄
	char phone[NAMELEN];		//电话
	char addr[DATALEN]; 		// 地址
	char work[DATALEN]; 		//职位
	char date[DATALEN];			//入职年月
	int level;					// 等级
	int salary;					// 工资
	
}staff_info_t;
 
/*定义双方通信的结构体信息*/
typedef struct 
{
	int  msgtype;       	 //请求的消息类型
	int  usertype;   		 //ADMIN 1	USER 2	   
	char username[NAMELEN];  //姓名
	char passwd[PASSLEN];	 //登陆密码
	char recvmsg[DATALEN];   //通信的消息
	int  flags;      		 //标志位
	staff_info_t info;       //员工信息
}MSG;
 
#define S_IP "10.0.12.9"
#define IP "192.168.250.100"
#define PORT "8888"
 
char user_name[NAMELEN];	 //姓名
char user_passwd[PASSLEN];	 //登陆密码
 
char history[DATALEN+100];
 
 
 
 
#endif
 

服务端

...

客户端

 
#include "common.h"

int do_login(int socketfd);
 
/**************************************
 *函数名:do_query
 *参   数:消息结构体
 *功   能:管理员查询
 ****************************************/
void do_admin_query(int sockfd, MSG *msg)
{
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = ADMIN_QUERY;
	char name[NAMELEN] = "";
	printf("Please enter find no:");
	scanf("%s", name);
	while (getchar() != '\n')
		;
	strcpy(msg->recvmsg, name);
	//发送查询请求
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
 
	//接受服务器响应
	while (1)
	{
		recv(sockfd, msg, sizeof(MSG), 0);
		if (!strncmp(msg->recvmsg, "end", 3))
		{
			printf("find success\n");
			return;
		}
		if (!strncmp(msg->recvmsg, "no", 2))
		{
			printf("find error\n");
			return;
		}
		printf("----------------------------------\n");
		printf("staffno :%d\nusertype:%d\nname    :%s\npasswd  :%s\nage     :%d\nphone   :%s\naddr    :%s\nwork    :%s\ndate    :%s\nlevel   :%d\nsalary  :%d\n", msg->info.no, msg->info.usertype, msg->info.name, msg->info.passwd, msg->info.age, msg->info.phone, msg->info.addr, msg->info.work, msg->info.date, msg->info.level, msg->info.salary);
		printf("----------------------------------\n");
	}
}
 
/**************************************
 *函数名:admin_modification
 *参   数:消息结构体
 *功   能:管理员修改
 ****************************************/
void do_admin_modification(int sockfd, MSG *msg) //管理员修改
{
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = ADMIN_MODIFY;
	int opt = 0;
	int tem;
	char str1[NAMELEN] = "";
	char str2[DATALEN] = "";
	char str3[PASSLEN] = "";
	printf("please enter user name:");
	scanf("%s",msg->username);
	printf("1:no\n2:usertype\n3:name\n4:passwd\n5:age\n6:phone\n7:addr\n8:work\n9:date\n10:level\n11:salary\nplease enter change option:");
	scanf("%d", &opt);
	while(getchar()!='\n');
	
	switch (opt)
	{
	case 1:
		msg->flags = 1;
		printf("please enter no:");
		scanf("%d", &tem);
		msg->info.no = tem;
		break;
	case 2:
		msg->flags = 2;
		printf("please enter usertype:");
		scanf("%d", &tem);
		msg->info.usertype = tem;
		break;
	case 3:
		msg->flags = 3;
		printf("please enter name:");
		fgets(str1,NAMELEN,stdin);
		str1[strlen(str1)-1]='\0';
		strcpy(msg->info.name, str1);
		break;
	case 4:
		msg->flags = 4;
		printf("please enter passwd:");
		fgets(str3,PASSLEN,stdin);
		str3[strlen(str3)-1]='\0';
		strcpy(msg->info.passwd, str1);
		break;
	case 5:
		msg->flags = 5;
		printf("please enter age:");
		scanf("%d", &tem);
		msg->info.age = tem;
		break;
	case 6:
		msg->flags = 6;
		printf("please enter phone:");
		fgets(str1,NAMELEN,stdin);
		str1[strlen(str1)-1]='\0';
		strcpy(msg->info.phone, str1);
		break;
	case 7:
		msg->flags = 7;
		printf("please enter addr:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.addr, str2);
		break;
	case 8:
		msg->flags = 8;
		printf("please enter work:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.work, str2);
		break;
	case 9:
		msg->flags = 9;
		printf("please enter date:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.date, str2);
		break;
	case 10:
		msg->flags = 10;
		printf("please enter level:");
		scanf("%d", &tem);
		msg->info.level = tem;
		break;
	case 11:
		msg->flags = 11;
		printf("please enter salary:");
		scanf("%d", &tem);
		msg->info.salary = tem;
		break;
	default:
		printf("enter error\n");
		return;
	}
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
	
 
	system("clear");
 
	recv(sockfd, msg, sizeof(MSG), 0);
	if (!strncmp(msg->recvmsg, "ok", 2))
	{
		printf("user change success\n");
		return;
	}
	else if(!strncmp(msg->recvmsg, "no", 2))
	{
		printf("user change error\n");
		return;
	}
	
}
 
/**************************************
 *函数名:admin_adduser
 *参   数:消息结构体
 *功   能:管理员创建用户
 ****************************************/
void do_admin_adduser(int sockfd, MSG *msg) //管理员添加用户
{
	system("clear");
	int tem;
	char str1[NAMELEN] = "";
	char str2[DATALEN] = "";
	char str3[PASSLEN] = "";
 
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = ADMIN_ADDUSER;
	printf("please enter no:");
	scanf("%d", &tem);
	msg->info.no = tem;
 
	printf("please enter usertype:");
	scanf("%d", &tem);
	msg->info.usertype = tem;
	while (getchar() != '\n');
 
	printf("please enter name:");
	fgets(str1,NAMELEN,stdin);
	str1[strlen(str1)-1]='\0';
	strcpy(msg->info.name, str1);
 
	printf("please enter passwd:");
	fgets(str3,PASSLEN,stdin);
	str3[strlen(str3)-1]='\0';
	strcpy(msg->info.passwd, str3);
 
	printf("please enter age:");
	scanf("%d", &tem);
	msg->info.age = tem;
	while (getchar() != '\n');
 
	printf("please enter phone:");
	fgets(str1,NAMELEN,stdin);
	str1[strlen(str1)-1]='\0';
	strcpy(msg->info.phone, str1);
 
	printf("please enter addr:");
	fgets(str2,DATALEN,stdin);
	str2[strlen(str2)-1]='\0';
	strcpy(msg->info.addr, str2);
 
	printf("please enter work:");
	fgets(str2,DATALEN,stdin);
	str2[strlen(str2)-1]='\0';
	strcpy(msg->info.work, str2);
 
	printf("please enter date:");
	fgets(str2,DATALEN,stdin);
	str2[strlen(str2)-1]='\0';
	strcpy(msg->info.date, str2);
 
	printf("please enter level:");
	scanf("%d", &tem);
	msg->info.level = tem;
 
	printf("please enter salary:");
	scanf("%d", &tem);
	msg->info.salary = tem;
 
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
 
	recv(sockfd, msg, sizeof(MSG), 0);
	if (!strncmp(msg->recvmsg, "ok", 2))
	{
		printf("user add success\n");
		return;
	}
	else if (!strncmp(msg->recvmsg, "no", 2))
	{
		printf("user add error\n");
		return;
	}
	
 
	printf("user add error\n");
}
 
/**************************************
 *函数名:admin_deluser
 *参   数:消息结构体
 *功   能:管理员删除用户
 ****************************************/
void do_admin_deluser(int sockfd, MSG *msg) //管理员删除用户
{
	system("clear");
	msg->msgtype = ADMIN_DELUSER;
	int no = 0;
	printf("pelase enter delete user NO:");
	scanf("%d", &no);
	msg->info.no = no;
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
	recv(sockfd, msg, sizeof(MSG), 0);
	if (!strncmp(msg->recvmsg, "ok", 2))
	{
		printf("user delete success\n");
		return;
	}
	else if (!strncmp(msg->recvmsg, "no", 2))
	{
		printf("user delete error\n");
		return;
	}
}
 
/**************************************
 *函数名:do_history
 *参   数:消息结构体
 *功   能:管理员查看历史记录
 ****************************************/
void do_admin_history(int sockfd, MSG *msg)
{
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = ADMIN_HISTORY;
	putchar(10);
 
	printf("   %s     |     %s     |                        %s                        \n","data","time","log");
 
 
 
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
	
	
 
	while (1)
	{
		recv(sockfd, msg, sizeof(MSG), 0);
		if (msg->flags == 1)
		{
			printf("find success\n");
			break;
		}
		if (msg->flags == 2)
		{
			printf("find error\n");
			break;
		}
 
		printf("%s",msg->recvmsg);
 
		send(sockfd, msg, sizeof(MSG), 0);
 
	}
 
}
 
void do_admin_list(int sockfd, MSG *msg)
{
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = ADMIN_LIST;
	char name[NAMELEN] = "";
	//发送查询请求
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
 
	//接受服务器响应
	while (1)
	{
		recv(sockfd, msg, sizeof(MSG), 0);
		if (!strncmp(msg->recvmsg, "endd", 4))
		{
			printf("find success\n");
			return;
		}
		if (!strncmp(msg->recvmsg, "no", 2))
		{
			printf("find error\n");
			return;
		}
		//printf("%d\t%d\t%s\t%s\t%d\t%s\t%s\t%s\t%s\t%d\t%d\n", msg->info.no, msg->info.usertype, msg->info.name, msg->info.passwd, msg->info.age, msg->info.phone, msg->info.addr, msg->info.work, msg->info.date, msg->info.level, msg->info.salary);
		printf("----------------------------------\n");
		printf("staffno :%d\nusertype:%d\nname    :%s\npasswd  :%s\nage     :%d\nphone   :%s\naddr    :%s\nwork    :%s\ndate    :%s\nlevel   :%d\nsalary  :%d\n", msg->info.no, msg->info.usertype, msg->info.name, msg->info.passwd, msg->info.age, msg->info.phone, msg->info.addr, msg->info.work, msg->info.date, msg->info.level, msg->info.salary);
		printf("----------------------------------\n");
 
		send(sockfd, msg, sizeof(MSG), 0);
	}
}
 
/**************************************
 *函数名:admin_menu
 *参   数:套接字、消息结构体
 *功   能:管理员菜单
 ****************************************/
void admin_menu(int sockfd, MSG *msg)
{
	int op = -1;
	printf(" ************ 1  查看   ************\n");
	printf(" ************ 2  修改   ************\n");
	printf(" ************ 3  添加   ************\n");
	printf(" ************ 4  删除   ************\n");
	printf(" ************ 5  列表   ************\n");
	printf(" ************ 6  清屏   ************\n");
	printf(" ************ 7 历史记录 ************\n");
	printf(" ************ 0 退回上级 ************\n");
	printf("请输入选项:");
	scanf("%d", &op);
	while(getchar()!='\n');
	if(op < 0 || op > 7)
	{
		system("clear");
		printf("输入错误 请重新输入\n");
		admin_menu(sockfd,msg);
	}
	switch (op)
	{
	case 0:
		system("clear");
		do_login(sockfd);
		break;
	case 1:
		do_admin_query(sockfd, msg);
		break;
	case 2:
		do_admin_modification(sockfd, msg);
		break;
	case 3:
		do_admin_adduser(sockfd, msg);
		break;
	case 4:
		do_admin_deluser(sockfd, msg);
		break;
	case 5:
		do_admin_list(sockfd, msg);
		break;
	case 6:
		system("clear");
		break;
	case 7:
		do_admin_history(sockfd,msg);
		break;
	default:
		printf("enter error\n");
		return;
	}
}
 
/**************************************
 *函数名:do_query
 *参   数:消息结构体
 *功   能:用户查找
 ****************************************/
void do_user_query(int sockfd, MSG *msg)
{
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = USER_QUERY;
	strcpy(msg->username, user_name);
	strcpy(msg->passwd,user_passwd);
	//发送查询请求
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
 
	//接受服务器响应
	while(1)
	{
	recv(sockfd, msg, sizeof(MSG), 0);
	if (!strncmp(msg->recvmsg, "end", 3))
	{
		printf("find success\n");
		return;
	}
	if (!strncmp(msg->recvmsg, "no", 2))
	{
		printf("find error\n");
		return;
	}
	printf("----------------------------------\n");
	printf("staffno :%d\nusertype:%d\nname    :%s\npasswd  :%s\nage     :%d\nphone   :%s\naddr    :%s\nwork    :%s\ndate    :%s\nlevel   :%d\nsalary  :%d\n", msg->info.no, msg->info.usertype, msg->info.name, msg->info.passwd, msg->info.age, msg->info.phone, msg->info.addr, msg->info.work, msg->info.date, msg->info.level, msg->info.salary);
	printf("----------------------------------\n");
	}
}
 
/**************************************
 *函数名:do_modification
 *参   数:消息结构体
 *功   能:用户修改
 ****************************************/
void do_user_modification(int sockfd, MSG *msg)
{
	
	system("clear");
	memset(msg, 0, sizeof(MSG));
	msg->msgtype = USER_MODIFY;
	strcpy(msg->username, user_name);
	strcpy(msg->passwd,user_passwd);
 
	int opt = 0;
	int tem;
	char str1[NAMELEN] = "";
	char str2[DATALEN] = "";
	char str3[PASSLEN] = "";
	printf("1:no\n2:usertype(Please contact the administrator)\n3:name\n4:passwd\n5:age\n6:phone\n7:addr\n8:work\n9:date\n10:level\n11:salary\nplease enter change option:");
	scanf("%d", &opt);
	while(getchar()!='\n');
	
	switch (opt)
	{
	case 1:
		msg->flags = 1;
		printf("please enter no:");
		scanf("%d", &tem);
		msg->info.no = tem;
		break;
	case 2:
		msg->flags = 2;
		printf("please enter usertype:");
		scanf("%d", &tem);
		msg->info.usertype = tem;
		break;
	case 3:
		msg->flags = 3;
		printf("please enter name:");
		fgets(str1,NAMELEN,stdin);
		str1[strlen(str1)-1]='\0';
		strcpy(msg->info.name, str1);
		break;
	case 4:
		msg->flags = 4;
		printf("please enter passwd:");
		fgets(str3,PASSLEN,stdin);
		str3[strlen(str3)-1]='\0';
		strcpy(msg->info.passwd, str3);
		break;
	case 5:
		msg->flags = 5;
		printf("please enter age:");
		scanf("%d", &tem);
		msg->info.age = tem;
		break;
	case 6:
		msg->flags = 6;
		printf("please enter phone:");
		fgets(str1,NAMELEN,stdin);
		str1[strlen(str1)-1]='\0';
		strcpy(msg->info.phone, str1);
		break;
	case 7:
		msg->flags = 7;
		printf("please enter addr:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.addr, str2);
		break;
	case 8:
		msg->flags = 8;
		printf("please enter work:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.work, str2);
		break;
	case 9:
		msg->flags = 9;
		printf("please enter date:");
		fgets(str2,DATALEN,stdin);
		str2[strlen(str2)-1]='\0';
		strcpy(msg->info.date, str2);
		break;
	case 10:
		msg->flags = 10;
		printf("please enter level:");
		scanf("%d", &tem);
		msg->info.level = tem;
		break;
	case 11:
		msg->flags = 11;
		printf("please enter salary:");
		scanf("%d", &tem);
		msg->info.salary = tem;
		break;
	default:
		printf("enter error\n");
		return;
	}
 
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return;
	}
	
 
	system("clear");
 
	recv(sockfd, msg, sizeof(MSG), 0);
	if (!strncmp(msg->recvmsg, "ok", 2))
	{
		printf("user change success\n");
		return;
	}
	else if(!strncmp(msg->recvmsg, "no", 2))
	{
		printf("user change error\n");
		return;
	}
}
 
/**************************************
 *函数名:user_menu
 *参   数:消息结构体
 *功   能:用户菜单
 ****************************************/
void user_menu(int sockfd, MSG *msg)
{
	int op = -1;
	printf(" ************ 1  查看  ************\n");
	printf(" ************ 2  修改  ************\n");
	printf(" ************ 3  清屏  ************\n");
	printf(" ************ 0  退回上级  *********\n");
	printf("请输入选项:");
	scanf("%d", &op);
	while(getchar()!='\n');
	if(op < 0 || op > 3)
	{
		system("clear");
		printf("输入错误 请重新输入\n");
		user_menu(sockfd,msg);
	}
	switch (op)
	{
	case 0:
		system("clear");
		do_login(sockfd);
		break;
	case 1:
		do_user_query(sockfd, msg);
		break;
	case 2:
		do_user_modification(sockfd, msg);
		break;
	case 3:
		system("clear");
		break;
	default:
		printf("enter error\n");
		break;
	}
}
 
int admin_or_user_login(int sockfd, MSG *msg)
{
	
	//输入用户名和密码
	memset(msg->username, 0, NAMELEN);
	printf("请输入用户名:");
	scanf("%s", msg->username);
	getchar();
 
	memset(msg->passwd, 0, DATALEN);
	printf("请输入密码: ");
	scanf("%s", msg->passwd);
	getchar();
 
	strcpy(user_name,msg->username);
	strcpy(user_passwd,msg->passwd);
 
	//发送登陆请求
	if (send(sockfd, msg, sizeof(MSG), 0) < 0)
	{
		printf("Sending the account to the server error\n");
		return -1;
	}
 
	//接受服务器响应
	recv(sockfd, msg, sizeof(MSG), 0);
 
	//判断是否登陆成功
	if (strncmp(msg->recvmsg, "OK", 2) == 0)
	{
		if (msg->usertype == ADMIN)
		{
			system("clear");
			printf("亲爱的管理员,欢迎您登陆员工管理系统!\n");
			while (1)
			{
				admin_menu(sockfd, msg);
			}
		}
		else if (msg->usertype == USER)
		{
			system("clear");
			printf("亲爱的用户,欢迎您登陆员工管理系统!\n");
			while (1)
			{
				user_menu(sockfd, msg);
			}
		}
	}
	else
	{
		printf("登陆失败!%s\n", msg->recvmsg);
		admin_or_user_login(sockfd,msg);
	}
 
	return 0;
}
 
/************************************************
 *函数名:do_login
 *参   数:套接字、消息结构体
 *返回值:是否登陆成功
 *功   能:登陆
 *************************************************/
int do_login(int socketfd)
{
	int n;
	MSG msg;
 
	while (1)
	{
		printf("**********************************\n");
		printf("********  1: 管理员模式   ********\n");
		printf("********  2:普通用户模式  ********\n");
		printf("********  0: 断开客户端    ********\n");
		printf("**********************************\n");
		printf("请输入您的选择(数字)>> ");
		scanf("%d", &n);
		while(getchar()!='\n');
		if(n < 0 || n > 2)
		{
			system("clear");
			printf("输入错误 请重新输入\n");
			do_login(socketfd);
		}
 
		switch (n)
		{
		case 1:
			//管理员模式登录
			msg.msgtype = ADMIN_LOGIN; // 1
			msg.usertype = ADMIN;	   // 0
			break;
		case 2:
			//普通用户登录
			msg.msgtype = USER_LOGIN;
			msg.usertype = USER;
			break;
		case 0:
			//退出
			msg.msgtype = QUIT;
			if (send(socketfd, &msg, sizeof(MSG), 0) < 0)
			{
				perror("do_login send");
				return -1;
			}
			close(socketfd);
			exit(0);
		default:
			printf("您的输入有误,请重新输入\n");
		}
 
		admin_or_user_login(socketfd, &msg);
	}
}
 
int main(int argc, const char *argv[])
{
	// socket->填充->绑定->监听->等待连接->数据交互->关闭
	system("clear");
	int socketfd;
	//创建网络通信的套接字 流式套接字
	if (-1 == (socketfd = socket(AF_INET, SOCK_STREAM, 0)))
	{
		printf("socket error\n");
		return -1;
	}
	printf("socket success\n");
 
	//填充网络结构体
	//填充服务器网路信息结构体
	struct sockaddr_in sin;
	//填充为IPV4地址
	sin.sin_family = AF_INET;
	//填充服务器IP
	sin.sin_addr.s_addr = inet_addr(IP);
	//填充服务器端口号
	sin.sin_port = htons(atoi(PORT));
 
	//连接服务器
	if (-1 == connect(socketfd, (struct sockaddr *)&sin, sizeof(sin)))
	{
		printf("connect error\n");
		return -1;
	}
	printf("connect suceess\n");
 
	//登陆
	do_login(socketfd);
 
	//关闭套接字
	close(socketfd);
 
	return 0;
}

测试现象

Ubuntu 18.04 PZB - VMware

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/193399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】极致详解:树与二叉树(下)——链式存储实现

目录 &#x1f929;前言&#x1f929;&#xff1a; &#x1f92f;一、链式存储概述&#x1f92f;&#xff1a; &#x1f920;二、链式结构的遍历&#x1f920;&#xff1a; 1.前序、中序与后序遍历&#xff1a; 2.层序遍历&#xff1a; &#x1f970;三、链式存储结构各接…

2023年转行IT互联网:盘点高薪职业岗位!

要问今年转行求职最想进入的行业&#xff0c;那么互联网肯定算其中一个。智联招聘发布的《2022大学生就业力调研报告》显示&#xff0c;IT/通信/电子/互联网行业是应届生最期望就业的行业。中国青年报中青校媒面向全国大学生发起调查&#xff0c;有64.33%希望毕业后能进入互联网…

linux常识及常用命令

一、介绍 一般项目都是部署在linux服务器上的&#xff0c;linux内核起初是由芬兰人林纳斯托瓦兹在上学时出于爱好编写的。它是一套免费试用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX&#xff08;可移植&#xff09;和UNIX的多用户、多任务、多线程和多CPU的操作…

Task10-Excel看板

文章目录一 分析思路二 实现过程1 确定周数2 销售基础整理3 周销售数据变化趋势4 周销售渠道整理5 看板绘制一 分析思路 二 实现过程 1 确定周数 确定日期所在的周数用&#xff1a;【WEEKNUM函数】 WEEKNUM&#xff08;serial_num&#xff0c;return_type&#xff09;参数Ser…

简介CSS

目录 一、CSS概述 二 、CSS的语法规则 三、CSS的引入方式 1、内部样式表 2、行内样式表 四、代码风格 1、紧凑风格 2、展开风格 五、选择器 1、基础选择器 标签选择器 类选择器 id选择器 通配符选择器 2、复合选择器 后代选择器 子选择器 并集选择器…

网络设备和常见网络拓扑

目录 集线器 网桥 交换机 路由器 常见网络拓扑 总线型 环形 星型 树型 网状 集线器 集线器的英文称为“Hub”。“Hub”是“中心”的意思&#xff0c;它的主要功能是对接收到的信号进行再生整形放大&#xff0c;以扩大网络的传输距离&#xff0c;同时把所有节点集中在…

threejs 几何图形 相交、差集、并集 插件

目前搜集到的有以下几个 THREE-CSGMeshhttps://github.com/manthrax/THREE-CSGMeshcsg.jshttps://github.com/jscad/csg.jsOctreeCSGhttps://github.com/giladdarshan/OctreeCSG/threeBSP 这个现在已经不更新了【对新版本不支持了geometry新版中移除了】threebsp 【这个是前辈…

Win10系统如何调整分区大小?

在使用Win10系统的过程中&#xff0c;如果电脑分区大小不合适或某个分区已满的问题可以通过调整分区大小来解决。可以缩小其他有闲置空余空间的分区&#xff0c;在得到未分配的空间后&#xff0c;然后将其分配到已满的分区&#xff0c;或者直接合并2个分区。接下来一起看看调整…

Elasticsearch Java入门

Elasticsearch安装 官网下载 下载的时候注意版本&#xff0c;spring boot如果用的是2.2版本就下载6.8的版本就行 下载完成之后解压&#xff0c;运行bin->elasticsearch.bat就可以启动服务了 做出win服务 elasticsearch-service.bat install浏览器输入localhost:9200 Ki…

BandZip cmd调用参数

命令行参数 Bandizip&#xff08;Bandizip.exe&#xff09;及其控制台应用程序&#xff08;bz.exe&#xff09;支持以下命令行参数&#xff1a; 注&#xff1a;推荐使用bz.exe&#xff0c;这个是专门给控制台的&#xff0c;更加稳定一些 # Bandizip.exe <archive> # Ban…

Linux中hosthost.confhost.allowhost.deny作用

可实现应急响应断网&#xff1a;阻止本机对恶意IP的访问链接 /etc/host.conf 为解析库声明的配置信息 /etc/hostname 配置主机名&#xff08;永久生效&#xff09; /etc/hosts 配置ip地址映射 /etc/hosts.allow 配置ip地址白名单 /etc/hosts.deny 配置ip地址黑名单 解…

Centos7安装jdk1.8tomcat

文章目录注意一 jdk1.8下载与安装1.1 JDK下载地址1.2 查看Centos7自带jdk版本1.2.1 第一种方式1.2.2 第二种方式1.2.3 第三种方式1.2.4 下载自带JDK1.2.5 安装JDK1.2.6 补充&#xff1a;查看jdk的安装目录1.2.7 配置环境变量二 tomcat下载与安装三 服务器运行项目模拟3.1 第一步…

EvilSelenium:一款功能强大的Chromium浏览器渗透测试工具

关于EvilSelenium EvilSelenium是一款基于 Selenium的渗透测试工具&#xff0c;该工具基于武器化的Selenium实现其功能&#xff0c;可以帮助广大研究人员针对基于Chromium的浏览器进行安全分析和渗透测试。 功能介绍 1、通过autofill获取存储的凭证信息&#xff1b; 2、获取C…

2023年黑马Java入门到精通教程--Java基础语法

java基础语法 变量详解 二进制 只有0、1&#xff0c;按照逢2进1的方式表示数据&#xff1a; 十进制转二进制的算法 除二取余法。 计算机中的数据的最小单位 其他数据形式是如何存储的 字符在计算机中是如何存储的呢&#xff1f; ASCII编码表&#xff1a;即美国信息交换标准…

代码随想录算法训练营第五十八天_第九章_动态规划 | 392.判断子序列、115.不同的子序列

LeetCode 392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 视频讲解https://www.bilibili.com/video/BV1tv4y1B7ym/?spm_id_from333.788&vd_sourcef98f2942b3c4cafea8907a325fc56a48文章讲解https://programmercarl.com/0392.%E5%88%A4%E6%96%A…

【Java线程】线程退出和终止

1. 线程终止 —— 通知方式 通过在 T1 线程中修改 T2 线程中的控制变量&#xff0c;来实现 T1 线程通知 T2 线程终止。 示例如下&#xff1a; /*** description: 线程的终止和退出测试* author: Liuwanqing* date: 2022-10-14 17:00*/ public class ThreadExit_ {public sta…

边缘检测与角点检测(模式识别与图像处理课程作业)

边缘检测与角点检测&#xff08;模式识别与图像处理课程作业&#xff09;一、边缘检测1.1、读取图像1.2、图像转换成灰度图像1.3、Sobel算子1.4、Canny算子1.5、显示正常中文的标签1.6、边缘检测结果二、角点检测2.1、读取图像2.2、图像转换成灰度图像2.3、Harris算子2.4、设置…

HTTPTunnel测试

介绍 HTTPTunnel是一个隧道软件。通过http的GET和POST请求隐藏隧道内的流量。适用于有网络封锁的环境&#xff0c;比如防火墙仅允许80端口数据包通过&#xff0c;内部终端访问外部其他应用时&#xff0c;或者渗透测试时访问内部目标服务器的其他业务端口时&#xff0c;都可以通…

MySQL多表操作案例练习

目录 准备 需求 代码 准备 -- 创建test1数据库 create database test1; -- 选择使用test1数据库 use test1; -- 创建部门表 create table dept(deptno int primary key,-- 部门编号dname varchar(14) ,-- 部门名称loc varchar(13) -- 部门地址 ) ;insert into dept values(…

【Rust】19. 模式与模式匹配

19.1 所有可能会用到模式的位置 19.1.1 match 分支 19.1.2 if let 条件表达式 可以组合并匹配 if let、else if 和 else if let 表达式&#xff0c;优势在于可以将多个值与模式比较&#xff08;match 表达式一次只能将一个值与模式比较&#xff09;&#xff0c;且各个分支并不…