初步计划,这个聊天平台不要UI,但支持功能有:
- 创建账号密码
- 建立聊天室(对应命令'$create')
- 加入房间(对应命令'$enter')
- 退出房间(对应命令'$exit')
- 有在线时长属性,下线后上线不会消失(在线时长保存在文件中)
- 支持私聊,大厅聊天,房间聊天三种方式(私聊对应命令'$private')
- 可以看到房间列表,在房间里面可以看到房间的成员列表(对应命令'$list')
- 在房间中,每过半小时服务器会发布4个1-10的数字,进行21点的小游戏,表达式最接近21点者获胜,相同结果则取最快者(输入答案对应命令'$game')
开始动手设计
报文传输使用TCP,因为TCP发送会等待缓冲区满或者超时才发包(nagle算法),所以要考虑粘包(当然也可以通过设置TCP的TCP_NODELAY选项避免这一项)
报文类型(type):注册、创建聊天室、进入聊天室、退出聊天室、发送给聊天室的报文、私聊的报文、21点游戏的报文
服务器需要保存的文件:所有个人账号及其信息(密码,在线总时长)
服务器数据结构:在线个人账号的字典(socketfd,房间号、登陆时间、标记是否已经参加游戏)、房间号字典(房间密码,房间人数,对应的成员socketfd,游戏信息(题目,目前最佳答案,目前获胜者))
服务器:创建事件列表,由接收报文触发事件组成,另起一个线程作为定时器,到了整点和半点向所有房间发送21点游戏题目
客户端:监听接收报文,另起线程监听控制台输入
列表负责监听socket,如果是服务器socketfd触发调用accept,就将新的socketfd加入输入事件列表,等待对端端报文;如果是连接的socketfd触发则recv报文。对于接收的报文处理有以下几种:
- 注册报文(type:1, user:??????, password:******):
- 遍历账号文件,每行表示一个账号信息,看这个user是否已经存在,如果存在则进行步骤2,如果不存在则进行步骤3;
- 回复报文(type:11, user:??????, errorcode:1)给客户端;
- 将新的账号密码信息加入到账号文件末尾一行,如果添加信息失败,进行步骤4,如果成功进行步骤5;
- 回复报文(type:11, user:??????, errorcode:2)给客户端;
- 回复报文(type:11, user:??????, errorcode:0)给客户端。
- 创建聊天室报文(type:2, user:??????, room:??????, password:******):
- 是否存在该房间号,如果存在则进行步骤2,如果不存在则进行步骤3;
- 回复报文(type:12, room:??????, errorcode:1)给客户端;
- 将新的账号密码等信息加入到聊天室账号字典,进行步骤5;
- 回复报文(type:12, room:??????, errorcode:0)给客户端。
- 进入聊天室报文(type:3, user:??????, room:??????, password:******):
- 是否存在该房间号,如果存在则进行步骤2,如果不存在则进行步骤3;
- 核对密码是否匹配,如果匹配进行步骤4,不匹配进行步骤6;
- 回复报文(type:13, room:??????, errorcode:1);
- 将文件中的该房间人数+1,进行步骤5;
- 将房间号加入到报文user对应信息,进行步骤7;
- 回复报文(type:13, room:??????, errorcode:2);
- 回复报文(type:13, room:??????, errorcode:0)。
- 退出聊天室报文(type:4, user:??????):
- 找到user对应的聊天室账号;
- 将user信息中的房间号重置为空,聊天室账号信息成员人数-1,若人数为0,进行步骤3,若人数不为0,进入步骤4;
- 删除该聊天室信息,进行步骤5;
- 回复报文(type:14, room:??????, errorcode:0)。
- 发送给聊天室的报文(type:5, user:??????, room:??????, content:"......"):
- 根据房间号,查看对应的个人账号,对其转发2;
- 发送(type:15, user:??????, room:??????, content:"......")。
- 私聊的报文(type:6, user:??????, target:??????, content:"......"):
- 该user是否在线,如果不在线,进行步骤2,如果存在进行步骤3;
- 回复报文(type:16, user:??????, target:??????);
- 转发报文(type:16, user:??????, target:??????, content:"......")。
- 登陆报文(type:7, user:??????, password:??????):
- 遍历账号文件,查看是否存在该账号,若不存在,则进行步骤3,若存在则进行步骤2;
- 核对密码,如果密码错误,则进行步骤4,若正确,进行步骤5;
- 回复报文(type:17, errorcode:1);
- 回复报文(type:17, errorcode:2);
- 将账号信息加到在线字典里并回复报文(type:17, errorcode:0)。
- 21点小游戏题目报文(type:8, room:??????, num:[????])
- 21点小游戏答案报文(type:18, user:??????, room:??????, ans:??):
- 根据ans内容保存最佳答案以及其提供者
- 15秒后发送排名第一的user给房间各成员(type:10, room:??????, user:??????),若没有成员提供答案则发送(type:10, room:??????, user:'')。