原型void ClientLogic::requestForceRefreshCoreData()
执行流程
- 校验认证状态
- 重置必要 pending 标记
- 拉取好友列表
- 拉取群组列表
- 拉取消息中心
关联接口
ClientLogic::requestPullFriendsClientLogic::requestPullGroupsClientLogic::requestPullNotifications
查看完整实现
clientlogic.cpp
void ClientLogic::requestForceRefreshCoreData()
{
if (!hasValidAuth("同步数据")) {
return;
}
m_pullNotificationsPending = false;
m_pullFriendsPending = false;
m_pullGroupsPending = false;
requestPullNotifications();
requestPullFriends();
requestPullGroups();
}
原型void NetworkServer::start()
执行流程
- 等待 epoll 事件
- recvfrom 读取数据
- 校验包体
- tryEnqueue 投递业务
- 执行会话清理
关联接口
ThreadPool::tryEnqueueBusinessHandler::dispatchTaskNetworkServer::removeExpiredSessions
查看完整实现
network_server.cpp
void NetworkServer::start()
{
if (server_fd < 0 || epoll_fd < 0 || !handler) {
std::cerr << "❌ [UDP 服务器] 初始化失败,无法启动主循环。\n";
return;
}
running.store(true);
epoll_event events[MAX_EPOLL_EVENTS];
int64_t lastSessionCleanup = nowSeconds();
char buffer[65535];
while (running.load()) {
int n = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS, 1000);
const int64_t now = nowSeconds();
if (now - lastSessionCleanup >= 5) {
removeExpiredSessions(35);
lastSessionCleanup = now;
}
if (n < 0) {
if (errno == EINTR) {
continue;
}
std::cerr << "❌ [UDP 服务器] epoll_wait 失败: " << strerror(errno) << "\n";
break;
}
for (int i = 0; i < n; ++i) {
if (events[i].data.fd != server_fd) {
continue;
}
if (events[i].events & (EPOLLERR | EPOLLHUP)) {
std::cerr << "⚠️ [UDP 服务器] epoll 返回错误事件: events="
<< events[i].events << "\n";
continue;
}
while (true) {
sockaddr_in client_addr{};
socklen_t addr_len = sizeof(client_addr);
ssize_t len = recvfrom(
server_fd,
buffer,
sizeof(buffer),
0,
reinterpret_cast<sockaddr*>(&client_addr),
&addr_len
);
if (len > 0) {
std::string data(buffer, static_cast<std::size_t>(len));
if (static_cast<std::size_t>(len) > MAX_UDP_PAYLOAD_BYTES) {
std::cerr << "⚠️ [UDP 服务器] 收到超大 UDP 包 len="
<< len << " from=" << addrToString(client_addr) << "\n";
}
bool queued = pool.tryEnqueue([this, data, client_addr]() {
if (!this->handler) {
return;
}
this->handler->dispatchTask(data, client_addr);
});
if (!queued) {
static std::atomic<unsigned long long> droppedTasks{0};
unsigned long long dropped = ++droppedTasks;
if (dropped <= 10 || dropped % 100 == 0) {
std::cerr << "⚠️ [UDP 服务器] 线程池队列已满,丢弃业务包"
<< " dropped=" << dropped
<< " pending=" << pool.pendingTasks()
<< " active=" << pool.activeTasks()
<< " completed=" << pool.completedTasks()
<< " rejected=" << pool.rejectedTasks()
<< "\n";
}
}
continue;
}
if (len == 0) {
break;
}
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
}
if (errno == EINTR) {
continue;
}
std::cerr << "⚠️ [UDP 服务器] recvfrom 失败: "
<< strerror(errno) << "\n";
break;
}
}
}
running.store(false);
}
原型void BusinessHandler::dispatchTask(const std::string& json_str, struct sockaddr_in client_addr)
参数
| 参数 | 说明 |
|---|
json_str | 原始业务 JSON |
client_addr | 请求来源地址 |
执行流程
- 解析 JSON
- 校验对象与 cmd
- 匹配命令分支
- 调用具体处理器
- 捕获解析与业务异常
关联接口
BusinessHandler::handleLoginBusinessHandler::handleGroupChatBusinessHandler::handleMediaVideoBusinessHandler::handleGameStart
查看完整实现
business_handler.cpp
void BusinessHandler::dispatchTask(const std::string& json_str,
struct sockaddr_in client_addr)
{
try {
json j = json::parse(json_str);
if (!j.is_object()) {
sendSimpleError(net_server, client_addr, "error", "请求 JSON 必须是对象");
return;
}
std::string cmd = getStringField(j, "cmd");
if (cmd.empty()) {
sendSimpleError(net_server, client_addr, "error", "缺少 cmd 字段");
return;
}
if (cmd == "login") {
handleLogin(json_str, client_addr);
} else if (cmd == "register") {
handleRegister(json_str, client_addr);
} else if (cmd == "heartbeat") {
handleHeartbeat(json_str, client_addr);
} else if (cmd == "send_chat" || cmd == "chat") {
handleChatRelay(json_str, client_addr);
} else if (cmd == "sync_chat" || cmd == "pull_history") {
handleSyncChat(json_str, client_addr);
} else if (cmd == "add_friend") {
handleAddFriend(json_str, client_addr);
} else if (cmd == "pull_friends") {
handlePullFriends(json_str, client_addr);
} else if (cmd == "pull_notifications") {
handlePullNotifications(json_str, client_addr);
} else if (cmd == "process_notification") {
handleProcessNotification(json_str, client_addr);
} else if (cmd == "pull_friend_requests") {
handlePullFriendRequests(json_str, client_addr);
} else if (cmd == "process_friend_req") {
handleProcessFriendReq(json_str, client_addr);
} else if (cmd == "delete_friend") {
handleDeleteFriend(j, client_addr, net_server);
} else if (cmd == "call") {
handleCall(json_str, client_addr);
} else if (cmd == "accept") {
handleAccept(json_str, client_addr);
} else if (cmd == "reject") {
handleRejectCall(json_str, client_addr);
} else if (cmd == "call_end") {
handleEndCall(json_str, client_addr);
} else if (cmd == "media_audio") {
handleMediaAudio(json_str, client_addr);
} else if (cmd == "media_video") {
handleMediaVideo(json_str, client_addr);
} else if (cmd == "invite_group_member") {
handleInviteGroupMember(json_str, client_addr);
} else if (cmd == "create_group") {
handleCreateGroup(json_str, client_addr);
} else if (cmd == "pull_groups") {
handlePullGroups(json_str, client_addr);
} else if (cmd == "pull_group_members") {
handlePullGroupMembers(json_str, client_addr);
} else if (cmd == "group_chat") {
handleGroupChat(json_str, client_addr);
} else if (cmd == "sync_group_chat") {
handleSyncGroupChat(json_str, client_addr);
} else if (cmd == "group_media_video") {
handleGroupMediaVideo(json_str, client_addr);
} else if (cmd == "group_media_video_control") {
handleGroupMediaVideoControl(json_str, client_addr);
} else if (cmd == "group_media_audio") {
handleGroupMediaAudio(json_str, client_addr);
} else if (cmd == "create_game_room") {
handleCreateGameRoom(json_str, client_addr);
} else if (cmd == "game_join_room") {
handleGameJoinRoom(json_str, client_addr);
} else if (cmd == "game_pull_room") {
handleGamePullRoom(json_str, client_addr);
} else if (cmd == "game_update_config") {
handleGameUpdateConfig(json_str, client_addr);
} else if (cmd == "game_ready") {
handleGameReady(json_str, client_addr);
} else if (cmd == "game_start") {
handleGameStart(json_str, client_addr);
} else if (cmd == "game_end_room") {
handleGameEndRoom(json_str, client_addr);
} else if (cmd == "cloud_factorio_status") {
handleCloudFactorioStatus(json_str, client_addr);
} else if (cmd == "cloud_factorio_start") {
handleCloudFactorioStart(json_str, client_addr);
} else if (cmd == "cloud_factorio_query") {
handleCloudFactorioQuery(json_str, client_addr);
} else if (cmd == "cloud_factorio_stop") {
handleCloudFactorioStop(json_str, client_addr);
} else if (cmd == "cloud_factorio_export_save") {
handleCloudFactorioExportSave(json_str, client_addr);
} else {
std::cout << "⚠️ [服务器中转] 收到无法识别的未知指令: "
<< cmd << "\n";
sendSimpleError(net_server, client_addr, "error", "未知 cmd: " + cmd);
}
} catch (const json::parse_error& e) {
std::string preview = json_str.substr(0, 200);
std::cerr << "JSON 解析错误,数据长度: " << json_str.size()
<< ",错误: " << e.what()
<< ",前200字节: " << preview << "\n";
sendSimpleError(net_server, client_addr, "error", "JSON 解析失败");
} catch (const std::exception& e) {
std::cerr << "dispatchTask 业务分发异常: " << e.what() << "\n";
sendSimpleError(net_server, client_addr, "error", "服务器业务分发异常");
}
}
原型void NetworkServer::sendData(const std::string& data, sockaddr_in dest_addr)
参数
| 参数 | 说明 |
|---|
data | 待发送数据 |
dest_addr | 目标客户端地址 |
执行流程
- 校验服务状态
- 锁定发送资源
- sendto 发送
- 记录发送异常
关联接口
BusinessHandler::notifyNotificationsChangedNetworkServer::getUserAddress
查看完整实现
network_server.cpp
void NetworkServer::sendData(const std::string& data, sockaddr_in dest_addr)
{
if (server_fd < 0) {
return;
}
if (data.empty()) {
return;
}
if (data.size() > MAX_UDP_PAYLOAD_BYTES) {
std::cerr << "⚠️ [UDP 服务器] sendData 包过大 size="
<< data.size()
<< ",可能发生 UDP 分片/丢包\n";
}
if (dest_addr.sin_family != AF_INET || dest_addr.sin_port == 0) {
std::cerr << "⚠️ [UDP 服务器] sendData 目标地址非法\n";
return;
}
ssize_t sent = sendto(
server_fd,
data.data(),
data.size(),
0,
reinterpret_cast<sockaddr*>(&dest_addr),
sizeof(dest_addr)
);
if (sent < 0) {
std::cerr << "⚠️ [UDP 服务器] sendto 失败: "
<< strerror(errno) << "\n";
return;
}
if (static_cast<std::size_t>(sent) != data.size()) {
std::cerr << "⚠️ [UDP 服务器] sendto 长度异常 sent="
<< sent << " total=" << data.size() << "\n";
}
}
原型void BusinessHandler::notifyNotificationsChanged(const std::string& targetUser, const std::string& reason, const json& extra)
参数
| 参数 | 说明 |
|---|
targetUser | 目标用户 |
reason | 状态变化原因 |
执行流程
- 查询目标在线地址
- 构造轻量事件
- 写入原因字段
- 发送到在线客户端
工程说明
推送事件只表达“数据已变化”,完整数据仍通过拉取接口获取。
关联接口
ClientLogic::requestForceRefreshCoreDataNetworkServer::getUserAddress
查看完整实现
business_handler.cpp
void BusinessHandler::notifyNotificationsChanged(const std::string& targetUser,
const std::string& reason,
const json& extra)
{
if (!net_server || targetUser.empty()) {
return;
}
Session targetSession;
if (!net_server->getSession(targetUser, targetSession)) {
return;
}
json notify;
notify["cmd"] = "notifications_changed";
notify["reason"] = reason;
if (extra.is_object()) {
for (auto it = extra.begin(); it != extra.end(); ++it) {
notify[it.key()] = it.value();
}
}
struct sockaddr_in targetAddr{};
targetAddr.sin_family = AF_INET;
inet_pton(AF_INET, targetSession.ip.c_str(), &targetAddr.sin_addr);
targetAddr.sin_port = htons(targetSession.port);
net_server->sendData(notify.dump(), targetAddr);
std::cout << "📨 [消息中心] 已通知在线用户 [" << targetUser
<< "] 刷新状态,reason=" << reason << "\n";
}