C++搭建集群聊天室(十五):客户端

js[“password”] = pwd;

string request = js.dump();

g_isLoginSuccess = false;

int len = send(clientfd, request.c_str(), strlen(request.c_str()) + 1, 0);

if (len == -1)

{

cerr << “send login msg error:” << request << endl;

}

sem_wait(&rwsem); // 等待信号量,由子线程处理完登录的响应消息后,通知这里

if (g_isLoginSuccess)

{

// 进入聊天主菜单页面

isMainMenuRunning = true;

mainMenu(clientfd);

}

}

break;

case 2: // register业务

{

char name[50] = {0};

char pwd[50] = {0};

cout << “username:”;

cin.getline(name, 50);

cout << “userpassword:”;

cin.getline(pwd, 50);

json js;

js[“msgid”] = REG_TYPE;

js[“name”] = name;

js[“password”] = pwd;

string request = js.dump();

int len = send(clientfd, request.c_str(), strlen(request.c_str()) + 1, 0);

if (len == -1)

{

cerr << “send reg msg error:” << request << endl;

}

sem_wait(&rwsem); // 等待信号量,子线程处理完注册消息会通知

}

break;

case 3: // quit业务

close(clientfd);

sem_destroy(&rwsem);

exit(0);

default:

cerr << “invalid input!” << endl;

break;

}

}

return 0;

}

// 处理注册的响应逻辑

void doRegResponse(json &responsejs)

{

if (0 != responsejs[“errno”].get()) // 注册失败

{

cerr << “name is already exist, register error!” << endl;

}

else // 注册成功

{

cout << "name register success, userid is " << responsejs[“id”]

<< “, do not forget it!” << endl;

}

}

// 处理登录的响应逻辑

void doLoginResponse(json &responsejs)

{

if (0 != responsejs[“errno”].get()) // 登录失败

{

cerr << responsejs[“errmsg”] << endl;

g_isLoginSuccess = false;

}

else // 登录成功

{

// 记录当前用户的id和name

g_currentUser.setID(responsejs[“id”].get());

g_currentUser.setname(responsejs[“name”]);

// 记录当前用户的好友列表信息

if (responsejs.contains(“friends”)) //如果有,贸然解析有崩溃的风险,JSON模块可脆弱

{

// 初始化

g_currentUserFriendList.clear();

vector vec = responsejs[“friends”];

for (string &str : vec)

{

json js = json::parse(str);

User user;

user.setID(js[“id”].get());

user.setname(js[“name”]);

user.setstate(js[“state”]);

g_currentUserFriendList.push_back(user);

}

}

// 记录当前用户的群组列表信息

if (responsejs.contains(“groups”))

{

// 初始化

g_currentUserGroupList.clear();

vector vec1 = responsejs[“groups”];

for (string &groupstr : vec1)

{

json grpjs = json::parse(groupstr);

Group group;

group.setId(grpjs[“id”].get());

group.setName(grpjs[“groupname”]);

group.setDesc(grpjs[“groupdesc”]);

vector vec2 = grpjs[“users”];

for (string &userstr : vec2)

{

GroupUser user;

json js = json::parse(userstr);

user.setID(js[“id”].get());

user.setname(js[“name”]);

user.setstate(js[“state”]);

user.setRole(js[“role”]);

group.getUsers().push_back(user);

}

g_currentUserGroupList.push_back(group);

}

}

// 显示登录用户的基本信息

showCurrentUserData();

// 显示当前用户的离线消息 个人聊天信息或者群组消息

if (responsejs.contains(“offlinemsg”))

{

vector vec = responsejs[“offlinemsg”];

for (string &str : vec)

{

json js = json::parse(str);

// time + [id] + name + " said: " + xxx

if (ONE_CHAT_MSG == js[“msgid”].get())

{

cout << js[“time”].get() << " [" << js[“id”] << “]” << js[“name”].get()

<< " said: " << js[“msg”].get() << endl;

}

else

{

cout << “群消息[” << js[“groupid”] << “]:” << js[“time”].get() << " [" << js[“id”] << “]” << js[“name”].get()

<< " said: " << js[“msg”].get() << endl;

}

}

}

g_isLoginSuccess = true;

}

}

// 子线程 - 接收线程

void readTaskHandler(int clientfd)

{

for (;😉

{

char buffer[1024] = {0};

int len = recv(clientfd, buffer, 1024, 0); // 阻塞了

if (-1 == len || 0 == len)

{

close(clientfd);

exit(-1);

}

// 接收ChatServer转发的数据,反序列化生成json数据对象

json js = json::parse(buffer);

int msgtype = js[“msgid”].get();

if (ONE_CHAT_MSG == msgtype)

{

cout << js[“time”].get() << " [" << js[“id”] << “]” << js[“name”].get()

<< " said: " << js[“msg”].get() << endl;

continue;

}

if (GROUP_CHAT_MSG == msgtype)

{

cout << “群消息[” << js[“groupid”] << “]:” << js[“time”].get() << " [" << js[“id”] << “]” << js[“name”].get()

<< " said: " << js[“msg”].get() << endl;

continue;

}

if (LOGIN_MSG_ACK == msgtype)

{

doLoginResponse(js); // 处理登录响应的业务逻辑

sem_post(&rwsem); // 通知主线程,登录结果处理完成

continue;

}

if (REG_MSG_ACK == msgtype)

{

doRegResponse(js);

sem_post(&rwsem); // 通知主线程,注册结果处理完成

continue;

}

}

}

// 显示当前登录成功用户的基本信息

void showCurrentUserData()

{

cout << “login user” << endl;

cout << “current login user => id:” << g_currentUser.getID() << " name:" << g_currentUser.getname() << endl;

cout << “----------------------friend list---------------------” << endl;

if (!g_currentUserFriendList.empty())

{

for (User &user : g_currentUserFriendList)

{

cout << user.getID() << " " << user.getname() << " " << user.getstate() << endl;

}

}

cout << “----------------------group list----------------------” << endl;

if (!g_currentUserGroupList.empty())

{

for (Group &group : g_currentUserGroupList)

{

cout << group.getId() << " " << group.getName() << " " << group.getDesc() << endl;

for (GroupUser &user : group.getUsers())

{

cout << user.getID() << " " << user.getname() << " " << user.getstate()

<< " " << user.getRole() << endl;

}

}

}

cout << “======================================================” << endl;

}

// “help” command handler

void help(int fd = 0, string str = “”);

// “chat” command handler

void chat(int, string);

// “addfriend” command handler

void addfriend(int, string);

// “creategroup” command handler

void creategroup(int, string);

// “addgroup” command handler

void addgroup(int, string);

// “groupchat” command handler

void groupchat(int, string);

// “loginout” command handler

void loginout(int, string);

// 系统支持的客户端命令列表

unordered_map<string, string> commandMap = {

{“help”, “显示所有支持的命令,格式help”},

{“chat”, “一对一聊天,格式chat:friendid:message”},

{“addfriend”, “添加好友,格式addfriend:friendid”},

{“creategroup”, “创建群组,格式creategroup:groupname:groupdesc”},

{“addgroup”, “加入群组,格式addgroup:groupid”},

{“groupchat”, “群聊,格式groupchat:groupid:message”},

{“loginout”, “注销,格式loginout”}};

// 注册系统支持的客户端命令处理

unordered_map<string, function<void(int, string)>> commandHandlerMap = {

{“help”, help},

{“chat”, chat},

{“addfriend”, addfriend},

{“creategroup”, creategroup},

{“addgroup”, addgroup},

{“groupchat”, groupchat},

{“loginout”, loginout}};

// 主聊天页面程序

void mainMenu(int clientfd)

{

help();

char buffer[1024] = {0};

while (isMainMenuRunning)

{

cin.getline(buffer, 1024);

string commandbuf(buffer);

string command; // 存储命令

int idx = commandbuf.find(“:”);

if (-1 == idx)

{

command = commandbuf;

}

else

{

command = commandbuf.substr(0, idx);

}

auto it = commandHandlerMap.find(command);

if (it == commandHandlerMap.end())

{

cerr << “invalid input command!” << endl;

continue;

}

// 调用相应命令的事件处理回调,mainMenu对修改封闭,添加新功能不需要修改该函数

it->second(clientfd, commandbuf.substr(idx + 1, commandbuf.size() - idx)); // 调用命令处理方法

}

}

// “help” command handler

void help(int, string)

{

cout << "show command list >>> " << endl;

for (auto &p : commandMap)

{

cout << p.first << " : " << p.second << endl;

}

cout << endl;

}

// “addfriend” command handler

void addfriend(int clientfd, string str)

{

int friendid = atoi(str.c_str());

json js;

js[“msgid”] = ADD_FRINEND_MSG;

js[“id”] = g_currentUser.getID();

js[“friendid”] = friendid;

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send addfriend msg error -> " << buffer << endl;

}

}

// “chat” command handler

void chat(int clientfd, string str)

{

int idx = str.find(“:”); // friendid:message

if (-1 == idx)

{

cerr << “chat command invalid!” << endl;

return;

}

int friendid = atoi(str.substr(0, idx).c_str());

string message = str.substr(idx + 1, str.size() - idx);

json js;

js[“msgid”] = ONE_CHAT_MSG;

js[“id”] = g_currentUser.getID();

js[“name”] = g_currentUser.getname();

js[“toid”] = friendid;

js[“msg”] = message;

js[“time”] = getCurrentTime();

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send chat msg error -> " << buffer << endl;

}

}

// “creategroup” command handler groupname:groupdesc

void creategroup(int clientfd, string str)

{

int idx = str.find(“:”);

if (-1 == idx)

{

cerr << “creategroup command invalid!” << endl;

return;

}

string groupname = str.substr(0, idx);

string groupdesc = str.substr(idx + 1, str.size() - idx);

json js;

js[“msgid”] = CREATE_GROUP_MSG;

js[“id”] = g_currentUser.getID();

js[“groupname”] = groupname;

js[“groupdesc”] = groupdesc;

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send creategroup msg error -> " << buffer << endl;

}

}

// “addgroup” command handler

void addgroup(int clientfd, string str)

{

int groupid = atoi(str.c_str());

json js;

js[“msgid”] = ADD_GROUP_MSG;

js[“id”] = g_currentUser.getID();

js[“groupid”] = groupid;

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send addgroup msg error -> " << buffer << endl;

}

}

// “groupchat” command handler groupid:message

void groupchat(int clientfd, string str)

{

int idx = str.find(“:”);

if (-1 == idx)

{

cerr << “groupchat command invalid!” << endl;

return;

}

int groupid = atoi(str.substr(0, idx).c_str());

string message = str.substr(idx + 1, str.size() - idx);

json js;

js[“msgid”] = GROUP_CHAT_MSG;

js[“id”] = g_currentUser.getID();

js[“name”] = g_currentUser.getname();

js[“groupid”] = groupid;

js[“msg”] = message;

js[“time”] = getCurrentTime();

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send groupchat msg error -> " << buffer << endl;

}

}

分享

1、算法大厂——字节跳动面试题

2、2000页互联网Java面试题大全

3、高阶必备,算法学习

ng str)

{

int idx = str.find(“:”);

if (-1 == idx)

{

cerr << “groupchat command invalid!” << endl;

return;

}

int groupid = atoi(str.substr(0, idx).c_str());

string message = str.substr(idx + 1, str.size() - idx);

json js;

js[“msgid”] = GROUP_CHAT_MSG;

js[“id”] = g_currentUser.getID();

js[“name”] = g_currentUser.getname();

js[“groupid”] = groupid;

js[“msg”] = message;

js[“time”] = getCurrentTime();

string buffer = js.dump();

int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);

if (-1 == len)

{

cerr << "send groupchat msg error -> " << buffer << endl;

}

}

分享

1、算法大厂——字节跳动面试题

[外链图片转存中…(img-4L82ZVhF-1716571575723)]

2、2000页互联网Java面试题大全

[外链图片转存中…(img-HXpk5MO6-1716571575724)]

3、高阶必备,算法学习

[外链图片转存中…(img-81fZt5yp-1716571575724)]

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值