聊天服务器-初始化用户配置文件

Posted by 周思进 on October 5, 2019

聊天服务器真是好久没弄了… 根据聊天服务器-需求分解中明确的用户信息先明文保存到本地实现,考虑如下两种方案:

1、用户信息直接按结构体二进制存储,可以有个文件头,包含一些版本号等等信息。

2、用户信息以可读形式的文本方式存储,这个就需要自己进行解析转换了,虽然查看方便,但操作读取相对麻烦。

综合考虑,方案一编写实现简单,所以选择方案一实现。


既然是文件的方式存储,这就涉及文件的相关操作,需要考虑如下几点:

一、系统初始化
系统开始起来并不存在用户配置文件,所以需要进行文件的创建操作,不过该操作只在系统第一次起来时需要进行,后面系统重启是不需要再重新创建了。

一般的流程就是通过access接口先判断文件存不存在,如果不存在,则进行创建打开,否则直接打开文件即可。不过access接口一般不推荐使用,原因是在access和实际open之前存在时间差,可能导致安全漏洞,建议直接open打开。

通过open接口来判断文件是否存在也有2种方式:
1、使用带有O_CREAT的标记来打开文件,这样如果初始文件不存在,会创建新的文件,不过打开的文件需要通过别的方式来判断是否是刚创建的文件,这个可以通过获取文件大小来判断,也有2种方式(这个放到后面再说吧)

2、先不带O_CREAT的方式尝试打开文件,如果失败了,则创建文件,并进行一些初始化文件写操作,如果打开文件成功则直接读取文件内容。

这2种方式初看之下可能也就直接选方式2了,当然我最终也选方式2,不过我还是要说下我的理解。

这里其实可以联系到平常我们写if_else判断语句,第一个判断语句其实是要考虑把最可能发生的事件写在最前面,不可能把不大可能发生的事件写在前面,否则这样的代码写的是不够好的。

同理考虑这里的文件初始化情况,这个只有一次,以后都是正常的打开操作即可,所以方式2除了第一次可能会先失败再走下创建流程操作,后面重启都是正常执行操作;而如果选择方式1,不说实现略麻烦,每次起来都需要通过获取文件大小的方式来判断,其实后面系统重启都是不必要的。

二、用户添加删除操作
我这边设计的用户配置信息存放在一个全局结构体中,如下:

typedef struct user_cfg
{
	LOGIN_USER login_user[MAX_USER_NUM];
	int cur_user_count;
}USER_CFG;

配置文件读写的就是这个结构体大小的数据,所以添加用户信息,就是往这个结构体中的数组空余位置进行赋值,然后将整个结构体再写入到文件中进行覆盖。这个倒是可以优化偏移到对应位置,只写那个用户的配置信息即可。

对于删除操作限定了只有admin用户有权限,所以在创建用户时对用户属性设置了对应权限,在删除操作时,判断下登入用户是否有权限进行删除操作。

另外就是删除一个用户后,需要考虑将后面的用户信息进行往前移位。如果不进行移位,添加新的用户查找插入位置就会麻烦,需要循环遍历数组哪个是空的,而移位后,只需要根据cur_user_count来确定要插入的位置。

PS:上面的方案也就我这样的练手项目搞搞,或者系统用户信息就是很少,如果用户数量很大,那还是得搞数据库,数据库这块后面也考虑学习下再替换掉当前的配置文件方案。全局变量这块也得换成链表的形式,否则每次数组移位也是很大一笔开销。