2021-10-13 Linux操作系统实验四:综合应用

Linux操作系统实验四:综合应用

题目

【实验目的】

进一步提高对操作系统的理解,提高在 Linux 操作系统下系
统编程开发的综合能力。提升编程能力,培养分析问题和独立解
决问题的能力。

【实验预备内容】

阅读参考资料,结合自选应用背景查找学习相关技术。

【实验内容】

分析示例程序代码,自由选定应用背景,用 C 语言编程实现
以下要求。

  • 模拟一个有应用背景的客户端、服务器交互类应用。

系统要求人机交互友好,便于演示和理解。系统实现可在使用 c 语言和 linux 系统调用的基础上允许增加其他非 c 语言功能。如程序功能较复杂,代码量大可团队 2-3 人一起合作完成,但要分工明确,各自承担工作量饱满,组员之间实验报告内容不允许重复。

学号:021900208 姓名:高旭 专业:计算机科学与技术 班级:02

一、实验环境:

Oracle VM VirtualBox、Ubuntu(64-bit)

二、报告内容:

1.系统开发情况介绍:

①系统设计背景说明:

某学院活动报账系统
当活动数量多、需要报销物品繁杂的时候,如果有一个报账系统能够在网络上提供报账申请与销账平台显然方便很多,所以本次我们两人决定通过网络编程、基于流的操作等知识模拟一个供组织内部使用的报账系统。主要有两个模块:(1)账号管理平台(2)报账管理平台。

②需求说明:

实现一个系统可以供某组织内部人员实现报账管理。
(1)能够权限分级。
(2)账号登录。
(3)活动报销申请。
(4)管理员完成报销申请。
(5)显示报销具体信息,如经办人、处理该报销的负责人、申请时间、报销时间、报销的项目详情等。

  • UML用例图一
    在这里插入图片描述

  • UML用例图二

在这里插入图片描述

③所使用的主要系统调用或功能:

  • Make命令
  • TCP的socket网络编程
  • 流打开与关闭
  • 基于流的I/O操作
  • 系统时间调用

④程序文件组成情况:

manage_user.h:

  • 用户结构体定义
  • 添加用户函数
  • 删除用户函数
  • 修改用户函数
  • 查找用户函数

manage_bill.h:

  • 活动结构体定义
  • 报销明细结构体定义
  • 活动查询函数
  • 查询报销函数
  • 申请报销函数
  • 删除报销函数
  • 处理报销函数

myser.c:

  • 创建socket描述符
  • bind绑定描述符
  • 服务器开启监听
  • 接收客户端连接请求并开始通信
  • 调用两个头文件函数
  • 程序内实现活动删除功能
  • 程序内实现活动创建功能
  • 程序内实现活动选择功能

mycli.c

  • 创建socket描述符
  • 设置服务器地址
  • 请求连接并开始通信

⑤代码行数:

代码 行数
manage_user.h 138
manage_bill.h 154
myser.c 420
mycli.c 405
合计 1117

⑥分工情况:

队员一 队员二
阶段一(10.9) 需求分析与设计 UML用例图
阶段二(10.10) 实现客户端与服务器网络通信 编写 manage_user.h 与 manage_bill.h 代码
阶段三(10.11-10.13) 设计通信顺序,实现整体代码框架,指定函数接口位置 将函数填入接口
工作量占比 50% 50%

2.程序运行演示

编译运行:

  • 编写Makefile工程文件:
    在这里插入图片描述
  • 使用make命令:
    在这里插入图片描述

主要功能界面与说明:

  • 管理员的用户管理平台
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  • 管理员的报账系统
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 普通用户的用户管理平台
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 普通用户的报账系统

在这里插入图片描述
在这里插入图片描述


3.实验结果总结:

完成效果:

  • 实现了用户账号管理与权限分级功能
  • 对用户账号进行存储
  • 实现活动创建,账目管理功能

优缺点与改进方向:

优点

  • 能够对用户进行权限分级。
  • 使用账号登录。
  • 能够存取用户账号密码。
  • 含有报账的详细信息,如申请、报销时间、经办人、负责人等。

缺点

  • 普通用户不能修改自己账号密码。
  • 没有最高级别的根用户,若需要对管理员账号进行管理只能手动修改用户文件。
  • 在TCP通信时,没有对socket的recv缓冲区处理,导致服务器有是没有在执行read()时候阻塞而是读入了乱码,导致信息交互出现问题,系统崩溃
  • 没有实现GUI比较可惜

改进方向

  • 对socket的recv缓冲区进行处理,防止误读
  • 使用GTK+或是QT等GUI工具,实现用户图形界面,提升人机交互感受

4.编程工作总结:

队员一:(主要负责网络方向)

1.自学的知识

  • TCP网络通信
  • Linux系统的文件管理模式
  • Make命令及其相关工具
  • 通用套接口数据结构
  • 字节操纵函数
  • IP地址转换函数
  • read/write与recv/send函数
  • socket套接口实现TCP通信流程

2.遇到的问题以及解决

3.创新设计

4.体会与收获

队员二:(主要负责基于流的文件存取)

1.自学的知识

  • Linux的文件描述符与流式文件
  • 流的打开与关闭(fopen与fclose)
  • 关于fopen()的参数type不同取值下的效果
  • 基于流的I/O操作(重点学习fread与fwrite)
  • Linux对于结构体的字节对齐方式
  • time_t类型以及相关函数

2.遇到的问题以及解决

3.创新设计

4.体会与收获

5.附源程序代码:

manage_bill.h

// manager_bill.h

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

struct object
{
    
    
    char item_name[15];
    char ad_name[15];
    time_t t;
};

struct bill
{
    
    
    char ob_name[15];  // 物品名称
    int num;           // 数量
    char unit[5];      // 单位
    double unit_pri;   // 单价
    double total;      // 总价
    time_t t1;         // 申请时间
    char ur_name[15];  // 经办人
    int solve;         // 是否已经报销
    time_t t2;         // 报销时间
    char ad_name[15];  // 负责人
    char comments[30]; // 备注
};

// 活动查询
int ob_query(struct object ob[], int num, char *name)
{
    
    
    int i;
    for (i = 0; i < num; i++)
    {
    
    
        if (strcmp(ob[i].item_name, name) == 0)
        {
    
    
            break;
        }
    }
    if (i == num)
    {
    
    
        return -1;
    }
    else
    {
    
    
        return i;
    }
}

// 物品查询
long int bill_query(char *pathname, char *name)
{
    
    
    FILE *fp = fopen(pathname, "rb");
    struct bill tmp_b;
    int found = 0;
    int cnt = 0;
    while (fread(&tmp_b, sizeof(struct bill), 1, fp))
    {
    
    
        if (strcmp(tmp_b.ob_name, name) == 0)
        {
    
    
            found = 1;
            break;
        }
        cnt++;
    }
    fclose(fp);
    if (found)
    {
    
    
        return cnt;
    }
    else
    {
    
    
        return -1;
    }
}

// 新增物品
int bill_insert(char *pathname, struct bill *b)
{
    
    
    FILE *fp = fopen(pathname, "a+b");
    if (fwrite(b, sizeof(struct bill), 1, fp))
    {
    
    
        fclose(fp);
        return 1;
    }
    else
    {
    
    
        fclose(fp);
        return 0;
    }
}

// 删除物品
int bill_remove(char *pathname, char *name)
{
    
    
    struct bill b;
    FILE *fp;
    FILE *fpn;
    if ((fpn = fopen("./tmpfile", "w")) == NULL)
    {
    
    
        return 0;
    }
    if ((fp = fopen(pathname, "r")) == NULL)
    {
    
    
        return 0;
    }
    while (fread(&b, sizeof(b), 1, fp) == 1) // 循环复制,与输入相匹配的不复制
    {
    
    
        if (strcmp(name, b.ob_name) != 0)
        {
    
    
            fwrite(&b, sizeof(b), 1, fpn); // 不相同,则复制
        }
        memset(&b, 0x00, sizeof(b));
    }
    fclose(fp);
    fclose(fpn);
    remove(pathname);              // 删除原档案文件
    rename("./tmpfile", pathname); // 复制好的新文件重命名为档案文件
    return 1;
}

int bill_update(char *pathname, char *ad_name, int i)
{
    
    
    FILE *fp;
    struct bill tmp_b;
    fp = fopen(pathname, "r+b");
    fseek(fp, i * sizeof(struct bill), SEEK_SET);
    fread(&tmp_b, sizeof(tmp_b), 1, fp);
    fseek(fp, i * sizeof(struct bill), SEEK_SET);
    if (tmp_b.solve)
    {
    
    
        fclose(fp);
        return 0;
    }
    else
    {
    
    
        tmp_b.solve = 1;
        strcpy(tmp_b.ad_name, ad_name);
        time(&tmp_b.t2);
        fwrite(&tmp_b, sizeof(tmp_b), 1, fp);
        fclose(fp);
        return 1;
    }
}

manage_user.h

// manager_user.h

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

#define ARFILE "./user.ar" // 指定档案文件的路径名称

// 用户的账号、密码、权限
struct userstruct
{
    
    
    char name[15];
    char password[15];
    int access;
};

// 删除用户函数
int removeuser(char *name)
{
    
    
    struct userstruct user;
    FILE *fp;
    FILE *fpn;
    int ret = 1;
    if ((fpn = fopen("./tmpfile", "w")) == NULL)
    {
    
    
        return 0;
    }
    if ((fp = fopen(ARFILE, "r")) == NULL)
    {
    
    
        return 0;
    }
    while (fread(&user, sizeof(user), 1, fp) == 1) // 循环复制,与输入姓名相匹配的不复制
    {
    
    
        if (strcmp(name, user.name) != 0)
        {
    
    
            fwrite(&user, sizeof(user), 1, fpn); // 不相同,则复制
        }
        else if (user.access == 1)
        {
    
    

            fwrite(&user, sizeof(user), 1, fpn); // 管理员,则复制
            ret = -1;
        }
        memset(&user, 0x00, sizeof(user));
    }
    fclose(fp);
    fclose(fpn);
    remove(ARFILE);              // 删除原档案文件
    rename("./tmpfile", ARFILE); // 复制好的新文件重命名为档案文件
    return ret;
}

// 查询员工函数
int queryuser(char *name)
{
    
    
    int found = 0;
    struct userstruct user;
    FILE *fp;
    if ((fp = fopen(ARFILE, "r")) == NULL)
    {
    
    
        return 0;
    }
    while (fread(&user, sizeof(user), 1, fp) == 1)
    {
    
    
        if (strcmp(name, user.name) == 0)
        {
    
    
            found = 1;
            break;
        }
        memset(&user, 0x00, sizeof(user));
    }
    fclose(fp);
    return found;
}

// 增加用户函数
int insertuser(struct userstruct ur)
{
    
    
    FILE *fp;
    if ((fp = fopen(ARFILE, "a")) == NULL)
    {
    
    
        return 0;
    }
    if (fwrite(&ur, sizeof(ur), 1, fp) < 0)
    {
    
    
        perror("fwrite");
        fclose(fp);
        return 0;
    }
    fclose(fp);
    return 1;
}

// 修改用户函数
int updateuser(struct userstruct new_user)
{
    
    
    struct userstruct old_user;
    FILE *fp;
    fpos_t pos;
    int found = -1;
    int cnt = 0;
    if ((fp = fopen(ARFILE, "r+")) == NULL)
    {
    
    
        return 0;
    }
    while (fread(&old_user, sizeof(old_user), 1, fp) == 1) // 循环复制,与输入姓名相匹配的不复制
    {
    
    
        if (strcmp(old_user.name, new_user.name) != 0)
        {
    
    
            cnt++;
        }
        else if (strcmp(old_user.name, new_user.name) == 0)
        {
    
    
            if (old_user.access)
            {
    
    
                return -2;
            }
            else
            {
    
    
                found = 1;
                pos.__pos = (long)(cnt * sizeof(struct userstruct)); // 设置移动量为一个结构体
                fsetpos(fp, &pos);                                   // 另外一种移动文件指针位置的方法
                fwrite(&new_user, sizeof(new_user), 1, fp);
            }
        }
        memset(&old_user, 0x00, sizeof(old_user));
    }
    return found;
}

myser.c

// myser.c

#include "manage_user.h"
#include "manage_bill.h"

#define PORT 6003	 // 端口号
#define MAXSIZE 1024 // 缓冲区大小

int running = 1;

void stop()
{
    
    
	running = 0;
}

int main(int argc, char *argv[])
{
    
    
	int sockfd, new_fd;				// 定义存放套接口描述符的变量
	struct sockaddr_in server_addr; // 定义服务器端套接口数据结构server_addr
	struct sockaddr_in client_addr; // 定义客户端套接口数据结构client_addr
	struct userstruct user;
	struct userstruct ur;
	int server_len, client_len; // 服务器和客户消息长度
	int nbytes, portnumber;
	int num;
	char name[10];
	char buf[MAXSIZE];
	char rebuf[MAXSIZE];
	char pathname[100];
	signal(SIGINT, stop); // 注册SIGINT信号
	FILE *fpn, *fp;
	fp = fopen("cata.txt", "r+b");
	struct object ob[100];
	for (num = 0; num < 100; num++)
	{
    
    
		if (fread(&ob[num], sizeof(struct object), 1, fp) < 1)
		{
    
    
			break;
		}
	}
	fclose(fp);
	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) // 服务器端开始建立socket描述符
	{
    
    
		fprintf(stderr, "Socket error:%s\n\a", strerror(errno));
		exit(1);
	}
	bzero(&server_addr, sizeof(struct sockaddr_in));									// 先将套接口地址数据结构清零
	server_addr.sin_family = AF_INET;													// 设为TCP/IP地址族
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);									// 设置本机地址并从主机字节序转换为网络字节序*/
	server_addr.sin_port = htons(PORT);													// 设置端口号并从主机字节序转换为网络字节序*/
	if (bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) // 调用bind函数绑定指定的端口号和ip地址到服务器创建的套接口
	{
    
    
		fprintf(stderr, "Bind error:%s\n\a", strerror(errno));
		exit(1);
	}
	if (listen(sockfd, 5) == -1) // 端口绑定成功,监听sockfd描述符,设置同时处理的最大连接请求数为5 */
	{
    
    
		fprintf(stderr, "Listen error:%s\n\a", strerror(errno));
		exit(1);
	}
	while (running)
	{
    
    
		client_len = sizeof(client_addr); // 接收客户端连接请求
		new_fd = accept(sockfd, (struct sockaddr *)&client_addr, (socklen_t *__restrict)&client_len);
		while (1)
		{
    
    
			read(new_fd, rebuf, sizeof(struct userstruct));
			printf("%s\n", rebuf);
			memcpy(&ur, rebuf, sizeof(ur));
			printf("%s,%s\n", ur.name, ur.password);
			struct userstruct user;
			FILE *fp;
			int found = 0;
			if ((fp = fopen(ARFILE, "rb")) == NULL)
			{
    
    
				return 0;
			}
			while (fread(&user, sizeof(user), 1, fp) == 1)
			{
    
    
				if (strcmp(ur.name, user.name) == 0)
				{
    
    
					found = 1;
					break;
				}
				memset(&user, 0x00, sizeof(user));
			}
			fclose(fp);
			if (found)
			{
    
    
				if (strcmp(ur.password, user.password) == 0)
				{
    
    
					if (user.access)
					{
    
    
						write(new_fd, "L1", 3);
					}
					else
					{
    
    
						write(new_fd, "L2", 3);
					}
					break;
				}
				else
				{
    
    
					write(new_fd, "ER", 3);
				}
			}
			else
			{
    
    
				write(new_fd, "NO", 3);
			}
		}
		while (1)
		{
    
    
			memset(rebuf, 0x00, sizeof(rebuf));
			read(new_fd, rebuf, sizeof(rebuf));
			printf("收到客户端消息: %s\n", rebuf); // 输出到终端
			if (rebuf[0] == '1')
			{
    
    
				while (1)
				{
    
    
					memset(rebuf, 0x00, sizeof(rebuf));
					read(new_fd, rebuf, sizeof(rebuf));
					printf("收到客户端消息: %s\n", rebuf); // 输出到终端
					if (rebuf[0] == '1')
					{
    
    
						write(new_fd, "请输入新用户名", MAXSIZE); // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						strcpy(user.name, rebuf);
						printf("收到客户端姓名消息: %s\n", user.name); // 输出到终端
						if (queryuser(user.name) == 1)
						{
    
    
							write(new_fd, "用户已存在!", MAXSIZE);
							continue;
						}
						write(new_fd, "请输入用户密码", MAXSIZE); // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						strcpy(user.password, rebuf);
						printf("收到客户端密码信息: %s\n", user.password);					  // 输出到终端
						write(new_fd, "如果该新添用户是管理员请输入y,否则输入n:", MAXSIZE); // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						printf("收到客户端权限消息: %s\n", rebuf); // 输出到终端
						if (rebuf[0] == 'y')
						{
    
    
							user.access = 1;
						}
						else if (rebuf[0] == 'n')
						{
    
    
							user.access = 0;
						}
						if (insertuser(user))
						{
    
    
							write(new_fd, "增加新用户成功...\n", MAXSIZE);
						}
						else
						{
    
    
							write(new_fd, "添加用户的时候发生了错误...\n", MAXSIZE);
						}
					}
					else if (rebuf[0] == '2')
					{
    
    
						write(new_fd, "请输入用户名", MAXSIZE); // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						printf("收到客户端查询用户是否存在消息: %s\n", rebuf); // 输出到终端
						if (queryuser(rebuf))
						{
    
    
							write(new_fd, "该用户存在\n", MAXSIZE);
						}
						else
						{
    
    
							write(new_fd, "没有找到该用户的数据...\n", MAXSIZE);
						}
					}
					else if (rebuf[0] == '3')
					{
    
    
						memset(&user, 0x00, sizeof(user));
						FILE *fp;
						if ((fp = fopen(ARFILE, "rb")) == NULL)
						{
    
    
							return 0;
						}
						while (fread(&user, sizeof(user), 1, fp) == 1)
						{
    
    
							write(new_fd, &user, sizeof(user));
							read(new_fd, rebuf, sizeof(rebuf));
						}
						fclose(fp);
						write(new_fd, "end", 4);
					}
					else if (rebuf[0] == '4')
					{
    
    
						write(new_fd, "请输入要删除的用户姓名:", MAXSIZE); // 回复消息
						read(new_fd, rebuf, 10);
						strcpy(name, rebuf);
						printf("收到客户端删除用户姓名消息: %s\n", name); // 输出到终端
						int ret = removeuser(name);
						if (ret == 1)
						{
    
    
							write(new_fd, "删除用户账号成功...\n", MAXSIZE);
						}
						else if (ret == -1)
						{
    
    
							write(new_fd, "不能删除管理员账号...\n", MAXSIZE);
						}
						else
						{
    
    
							write(new_fd, "删除用户账号发生了错误...\n", MAXSIZE);
						}
					}
					else if (rebuf[0] == '5')
					{
    
    
						write(new_fd, "请输入用户姓名", MAXSIZE); // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						strcpy(user.name, rebuf);
						printf("收到客户端修改用户名消息: %s\n", rebuf); // 输出到终端
						write(new_fd, "请输入用户密码", MAXSIZE);		 // 回复消息
						read(new_fd, rebuf, sizeof(rebuf));
						strcpy(user.password, rebuf);
						printf("收到客户端修改密码消息: %s\n", rebuf); // 输出到终端
						int ret = updateuser(user);
						if (ret == 1)
						{
    
    
							write(new_fd, "修改用户资料成功...\n", MAXSIZE);
						}
						else if (ret == -1)
						{
    
    
							write(new_fd, "没有该用户的数据...\n", MAXSIZE);
						}
						else if (ret == -2)
						{
    
    
							write(new_fd, "没有权限修改管理员账号...\n", MAXSIZE);
						}
						else
						{
    
    
							write(new_fd, "修改用户账号发生了错误...\n", MAXSIZE);
						}
					}
					else if (rebuf[0] == '0')
					{
    
    
						break;
					}
				}
			}
			else if (rebuf[0] == '2')
			{
    
    
				while (1)
				{
    
    
					memset(rebuf, 0x00, sizeof(rebuf));
					read(new_fd, rebuf, sizeof(rebuf));
					printf("收到客户端消息: %s\n", rebuf); // 输出到终端
					if (rebuf[0] == '1')
					{
    
    
						int index = 0;
						for (index; index < num; index++)
						{
    
    
							write(new_fd, &ob[index], sizeof(struct object));
							read(new_fd, rebuf, sizeof(rebuf));
						}
						write(new_fd, "end", 4);
					}
					else if (rebuf[0] == '2')
					{
    
    
						write(new_fd, "请输入活动名", MAXSIZE);
						read(new_fd, rebuf, 40);
						printf("收到客户端活动名消息: %s\n", rebuf); // 输出到终端
						int i = ob_query(ob, num, rebuf);
						if (i == -1)
						{
    
    
							write(new_fd, "该活动不存在!", 22);
						}
						else
						{
    
    
							strcat(pathname, ob[i].item_name);
							strcat(pathname, ".txt");
							struct bill b;
							write(new_fd, "加载成功", MAXSIZE);
							while (1)
							{
    
    
								fpn = fopen(pathname, "r+b");
								fseek(fp, 0 * sizeof(struct bill), SEEK_SET);
								while (fread(&b, sizeof(struct bill), 1, fpn))
								{
    
    
									write(new_fd, &b, sizeof(b));
									read(new_fd, rebuf, 3);
								}
								write(new_fd, "end", 4);
								fclose(fpn);
								read(new_fd, rebuf, MAXSIZE);
								printf("收到客户端消息:%s\n", rebuf);
								if (rebuf[0] == '1')
								{
    
    
									write(new_fd, "OK", MAXSIZE);
									read(new_fd, rebuf, sizeof(struct bill));
									struct bill *tmp_b = (struct bill *)&rebuf;
									if (bill_query(pathname, tmp_b->ob_name) < 0)
									{
    
    
										bill_insert(pathname, tmp_b);
										write(new_fd, "添加成功!", MAXSIZE);
									}
									else
									{
    
    
										write(new_fd, "该物品已经存在!", MAXSIZE);
									}
								}
								else if (rebuf[0] == '2')
								{
    
    
									write(new_fd, "请输入要删除的物品:", MAXSIZE);
									read(new_fd, rebuf, MAXSIZE);
									int i = bill_query(pathname, rebuf);
									if (i < 0)
									{
    
    
										write(new_fd, "该物品不存在!", MAXSIZE);
									}
									else
									{
    
    
										bill_remove(pathname, rebuf);
										write(new_fd, "删除物品成功!", MAXSIZE);
									}
								}
								else if (rebuf[0] == '3')
								{
    
    
									write(new_fd, "请输入要报销的物品:", MAXSIZE);
									read(new_fd, rebuf, MAXSIZE);
									int i = bill_query(pathname, rebuf);
									if (i < 0)
									{
    
    
										write(new_fd, "该物品不存在!", MAXSIZE);
									}
									else
									{
    
    
										if (bill_update(pathname, ur.name, i))
										{
    
    
											write(new_fd, "报销成功!", MAXSIZE);
										}
										else
										{
    
    
											write(new_fd, "报销失败,改物品已被报销!", MAXSIZE);
										}
									}
								}
								else if (rebuf[0] == '0')
								{
    
    
									break;
								}
							}
							strcpy(pathname, "./");
						}
					}
					else if (rebuf[0] == '3')
					{
    
    
						write(new_fd, "请输入活动名", MAXSIZE);
						read(new_fd, rebuf, 40);
						printf("收到客户端活动名消息: %s\n", rebuf); // 输出到终端
						if (ob_query(ob, num, rebuf) == -1)
						{
    
    
							strcat(pathname, rebuf);
							strcat(pathname, ".txt");
							fpn = fopen(pathname, "wb");
							strcpy(pathname, "./");
							fclose(fpn);
							struct object tmp_ob;
							strcpy(tmp_ob.ad_name, ur.name);
							strcpy(tmp_ob.item_name, rebuf);
							time(&tmp_ob.t);
							ob[num] = tmp_ob;
							num++;
							write(new_fd, "创建成功", MAXSIZE);
						}
						else
						{
    
    
							write(new_fd, "该活动已经存在!", MAXSIZE);
						}
					}
					else if (rebuf[0] == '4')
					{
    
    
						write(new_fd, "请输入活动名", MAXSIZE);
						read(new_fd, rebuf, 15);
						printf("收到客户端活动名消息: %s\n", rebuf); // 输出到终端
						int i = ob_query(ob, num, rebuf);
						printf("%d\n", i);
						if (i == -1)
						{
    
    
							write(new_fd, "该活动不存在!", MAXSIZE);
						}
						else
						{
    
    
							for (i = i + 1; i < num; i++)
							{
    
    
								ob[i - 1] = ob[i];
							}
							num--;
							strcat(pathname, rebuf);
							strcat(pathname, ".txt");
							remove(pathname);
							strcpy(pathname, "./");
							write(new_fd, "该活动成功删除!", MAXSIZE);
						}
					}
					else if (rebuf[0] == '0')
					{
    
    
						break;
					}
				}
			}
			else if (rebuf[0] == '0')
			{
    
    
				break;
			}
		}
		close(new_fd);
	}
	fp = fopen("cata.txt", "w+b"); // 写入活动信息
	int i = 0;
	for (i; i < num; i++)
	{
    
    
		fwrite(&ob[num], sizeof(struct object), 1, fp);
	}
	fclose(fp);
	close(sockfd);
	return 0;
}

mycli.c

// mycli.c

#include "manage_user.h"
#include "manage_bill.h"

#define PORT 6003    // 端口号
#define MAXSIZE 1024 // 缓冲区大小

int main(int argc, char *argv[])
{
    
    

    int new_fd;
    char buf[MAXSIZE];
    char rebuf[MAXSIZE];
    char c;
    struct sockaddr_in server_addr; // 定义服务器端套接口数据结构server_addr
    struct hostent *host;           // 定义一个hostent结构的指针
    struct userstruct user, me;
    host = gethostbyname("localhost");
    if ((new_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
    
    
        fprintf(stderr, "Socket Error:%s\a\n", strerror(errno));
        exit(1);
    }
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    if (connect(new_fd, (struct sockaddr *)(&server_addr), sizeof(server_addr)) == -1)
    {
    
    
        fprintf(stderr, "Connect Error:%s\a\n", strerror(errno));
        exit(1);
    }
    else
    {
    
    
        fprintf(stdout, "连接成功\n");
    }
    while (1)
    {
    
    
        printf("请输入用户账号:");
        scanf("%s", me.name);
        printf("请输入用户密码:");
        scanf("%s", me.password);
        write(new_fd, &me, sizeof(me));
        read(new_fd, rebuf, 3);
        if (strcmp(rebuf, "ER") == 0)
        {
    
    
            printf("密码错误!\n");
        }
        else if (strcmp(rebuf, "NO") == 0)
        {
    
    
            printf("账号不存在!\n");
        }
        else if (strcmp(rebuf, "L1") == 0)
        {
    
    
            me.access = 1;
            break;
        }
        else if (strcmp(rebuf, "L2") == 0)
        {
    
    
            me.access = 0;
            break;
        }
    }
    if (me.access)
    {
    
    
        printf("管理员%s您好,欢迎您使用报账系统!\n", me.name);
    }
    else
    {
    
    
        printf("用户%s您好,欢迎您使用报账系统!\n", me.name);
    }
    while (1)
    {
    
    
        printf("     *活动报账管理系统*\n");
        printf("-------------------------\n");
        printf("     1.进入用户管理       \n");
        printf("     2.进入报账系统       \n");
        printf("     0.退出系统           \n");
        printf("-------------------------\n");
        printf("请输入:");
        scanf("%s", buf);
        write(new_fd, buf, sizeof(buf)); // 发送消息
        if (buf[0] == '1')
        {
    
    
            while (1)
            {
    
    
                printf("       *用户管理平台*       \n");
                printf("---------------------------\n");
                printf("     1.添加新用户账号       \n");
                printf("     2.查找用户是否存在     \n");
                printf("     3.查看全部账号         \n");
                printf("     4.删除用户账号         \n");
                printf("     5.修改用户账号         \n");
                printf("     0.返回                \n");
                printf("---------------------------\n");
                printf("请输入:");
                scanf("%s", buf);
                if (buf[0] == '1' && me.access != 1)
                {
    
    
                    printf("对不起,您的权限不允许您添加用户\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                else if (buf[0] == '4' && me.access != 1)
                {
    
    
                    printf("对不起,您的权限不允许您删除用户\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                else if (buf[0] == '5' && me.access != 1)
                {
    
    
                    printf("对不起,您的权限不允许您修改用户\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                write(new_fd, buf, sizeof(buf)); // 发送消息
                if (buf[0] == '0')
                {
    
    
                    break;
                }
                else if (buf[0] == '1')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));                 // 接收新消息
                    printf("收到服务器消息:%s\n请输入用户名:", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    if (strcmp(rebuf, "用户已存在!") == 0)
                    {
    
    
                        printf("输入任意键继续...\n");
                        scanf("%s", buf);
                        continue;
                    }
                    printf("请输入用户密码:"); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));                 // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));              // 接收新消息
                    printf("收到服务器消息:%s\n请输入y/n:", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
                else if (buf[0] == '2')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
                else if (buf[0] == '3')
                {
    
    
                    printf("----------------用 户 列 表----------------\n");
                    read(new_fd, rebuf, sizeof(struct userstruct)); // 接收新消息
                    while (strcmp(rebuf, "end") != 0)
                    {
    
    
                        struct userstruct *ur = (struct userstruct *)&rebuf;
                        if (ur->access)
                        {
    
    
                            printf("用户名:%s  身份权限:管理员\n", ur->name);
                        }
                        else
                        {
    
    
                            printf("用户名:%s  身份权限:用户\n", ur->name);
                        }
                        write(new_fd, "OK", 3);
                        read(new_fd, rebuf, sizeof(struct userstruct));
                    }
                    printf("------------------到 底 啦------------------\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
                else if (buf[0] == '4')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, 10);               // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
                else if (buf[0] == '5')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
            }
        }
        else if (buf[0] == '2')
        {
    
    
            while (1)
            {
    
    
                printf("      *报账管理平台*        \n");
                printf("---------------------------\n");
                printf("     1.查看所有活动目录     \n");
                printf("     2.选择活动            \n");
                printf("     3.添加活动            \n");
                printf("     4.删除活动            \n");
                printf("     0.返回                \n");
                printf("---------------------------\n");
                printf("请输入:");
                scanf("%s", buf);
                if (buf[0] == '3' && me.access != 1)
                {
    
    
                    printf("对不起,您的权限不允许您添加活动\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                else if (buf[0] == '4' && me.access != 1)
                {
    
    
                    printf("对不起,您的权限不允许您删除活动\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                write(new_fd, buf, sizeof(buf)); // 发送消息
                if (buf[0] == '1')
                {
    
    
                    printf("----------------活 动 列 表----------------\n");
                    read(new_fd, rebuf, sizeof(struct object)); // 接收新消息
                    while (strcmp(rebuf, "end") != 0)
                    {
    
    
                        struct object *ob = (struct object *)&rebuf;
                        printf("活动项目:%s,创建人:%s,创建时间:%s", ob->item_name, ob->ad_name, asctime(localtime(&ob->t)));
                        write(new_fd, "OK", 3);
                        read(new_fd, rebuf, sizeof(struct object));
                    }
                    printf("------------------到 底 啦------------------\n");
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                }
                else if (buf[0] == '2')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    if (strcmp(rebuf, "该活动不存在!") == 0)
                    {
    
    
                        printf("输入任意键继续...\n");
                        scanf("%s", buf);
                    }
                    else
                    {
    
    
                        while (1)
                        {
    
    
                            printf("----------------账 目 列 表----------------\n");
                            read(new_fd, rebuf, sizeof(struct bill)); // 接收新消息
                            while (strcmp(rebuf, "end") != 0)
                            {
    
    
                                struct bill *b = (struct bill *)&rebuf;
                                if (b->solve)
                                {
    
    
                                    printf("物品:%s,数量:%d,单位:%s,单价:%.2lf,总价:%.2lf\n申请时间:%s经办人:%s,是否已经报销:是\n报销时间:%s负责人:%s,备注:%s\n", b->ob_name, b->num, b->unit, b->unit_pri, b->total, asctime(localtime(&b->t1)), b->ur_name, asctime(localtime(&b->t2)), b->ad_name, b->comments);
                                }
                                else
                                {
    
    
                                    printf("物品:%s,数量:%d,单位:%s,单价:%.2lf,总价:%.2lf\n申请时间:%s经办人:%s,是否已经报销:否\n报销时间:无\n负责人:无,备注:%s\n", b->ob_name, b->num, b->unit, b->unit_pri, b->total, asctime(localtime(&b->t1)), b->ur_name, b->comments);
                                }
                                printf("******************************************************************************************\n");
                                write(new_fd, "OK", 3);
                                read(new_fd, rebuf, sizeof(struct bill));
                            }
                            printf("------------------到 底 啦------------------\n");
                            printf("若要新增账目请输入1,删除账目请输入2,报销账目请输入3,返回请输入0\n请输入:");
                            scanf("%s", buf);
                            if (buf[0] == '2' && me.access != 1)
                            {
    
    
                                printf("对不起,您的权限不允许您删除账目\n");
                                printf("输入任意键继续...\n");
                                scanf("%s", buf);
                                continue;
                            }
                            else if (buf[0] == '3' && me.access != 1)
                            {
    
    
                                printf("对不起,您的权限不允许您报销账目\n");
                                printf("输入任意键继续...\n");
                                scanf("%s", buf);
                                continue;
                            }
                            write(new_fd, buf, MAXSIZE); // 发送消息
                            if (buf[0] == '1')
                            {
    
    
                                struct bill tmp_b;
                                read(new_fd, rebuf, MAXSIZE);
                                printf("请输入物品名称:");
                                scanf("%s", tmp_b.ob_name);
                                printf("请输入物品单位:");
                                scanf("%s", tmp_b.unit);
                                printf("请输入物品数量:");
                                scanf("%d", &tmp_b.num);
                                printf("请输入物品单价:");
                                scanf("%lf", &tmp_b.unit_pri);
                                printf("请输入备注:");
                                scanf("%s", tmp_b.comments);
                                tmp_b.total = tmp_b.unit_pri * tmp_b.num;
                                tmp_b.solve = 0;
                                strcpy(tmp_b.ur_name, me.name);
                                strcpy(tmp_b.ad_name, "NULL");
                                time(&tmp_b.t1);
                                time(&tmp_b.t2);
                                write(new_fd, &tmp_b, sizeof(tmp_b));
                                read(new_fd, rebuf, MAXSIZE);         // 接收新消息
                                printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                                printf("输入任意键继续...\n");
                                scanf("%s", buf);
                            }
                            else if (buf[0] == '2')
                            {
    
    
                                read(new_fd, rebuf, sizeof(rebuf)); // 接收新消息
                                printf("%s", rebuf);                // 输出到终端
                                scanf("%s", buf);
                                write(new_fd, buf, MAXSIZE);
                                read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                                printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                                printf("输入任意键继续...\n");
                                scanf("%s", buf);
                            }
                            else if (buf[0] == '3')
                            {
    
    
                                read(new_fd, rebuf, sizeof(rebuf)); // 接收新消息
                                printf("%s", rebuf);                // 输出到终端
                                scanf("%s", buf);
                                write(new_fd, buf, MAXSIZE);
                                read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                                printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                                printf("输入任意键继续...\n");
                                scanf("%s", buf);
                            }
                            else if (buf[0] == '0')
                            {
    
    
                                break;
                            }
                        }
                    }
                }
                else if (buf[0] == '3')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                else if (buf[0] == '4')
                {
    
    
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    scanf("%s", buf);
                    write(new_fd, buf, sizeof(buf));      // 发送消息
                    read(new_fd, rebuf, sizeof(rebuf));   // 接收新消息
                    printf("收到服务器消息:%s\n", rebuf); // 输出到终端
                    printf("输入任意键继续...\n");
                    scanf("%s", buf);
                    continue;
                }
                else if (buf[0] == '0')
                {
    
    
                    break;
                }
            }
        }
        else if (buf[0] == '0')
        {
    
    
            break;
        }
        else
        {
    
    
            printf("请输入正确的命令...\n");
        }
    }
    printf("结束通信\n");
    close(new_fd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ShakingSH/article/details/120743075