muduoネットワークライブラリを用いたクラスタチャットサーバーのフレンド機能実装

フレンド追加機能の実装

実装概要-簡易的なアプローチ

コンソールベースのフレンドリスト表示機能

  1. ユーザー認証後、サーバーがフレンド情報一覧を返却し、チャット相手を選択可能。
  2. フレンド追加処理クライアントからリクエストを受け、サーバーがfriendテーブルにユーザー関係を記録。

制限事項

本プロジェクトでは厳密なフレンド制約を設けておらず、IDと名前さえ分かれば誰とでもチャット可能。より高度な制約仕様は将来的な改善候補。

テーブル設計-個別処理ファイル対応

friendテーブルはuser_idおよびfriend_idの2カラムのみを含み、複合主キーで重複登録を防ぐ。

業務ロジック-改善余地あり

ユーザーは相手の承認なしに直接フレンド追加可能。追加時にuser_idfriend_idがDBに挿入され、検索時はJOINクエリで詳細情報を取得(パスワードは除外)。

機能制限の理由

C/C++はJavaやPHPと異なり、高レベルなフレームワークが組み込まれておらず、DB接続やクエリ処理などの詳細管理を自前で行う必要があり、複雑な業務ロジックの拡張に影響する。

最適化案

ログイン時のフレンドリストは頻繁に変化しないため、クライアント側にキャッシュすることでサーバー負荷を軽減。次回ログイン時以降に更新を反映。

SQL結合クエリ

複数テーブルから一度に情報を取得する結合クエリの実装例。

内結合(INNER JOIN):

  • 両テーブルに一致するレコードのみを返却。
  • 片方にマッチがない場合は結果に含まれない。
SELECT a.id, a.name, a.status 
FROM user a 
INNER JOIN friend b ON b.friendid = a.id 
WHERE b.userid=%d

左結合(LEFT JOIN):

  • 左テーブルの全レコードを返却。
  • 右テーブルにマッチがない場合、該当フィールドはNULLとなる。

SELECT u.id, u.name, f.friendid FROM user u LEFT JOIN friend f ON u.id = f.friendid;


### コード構成

**include/public.hpp**

ADD_FRIEND_MSG // フレンド追加メッセージ種別


**include/server/chatservice.hpp**

// フレンド追加処理 void handleFriendAddition(const TcpConnectionPtr &conn, json &js, Timestamp time); // 接続情報からユーザーを特定


**include/server/friendmodel.hpp**

#ifndef FRIEND_MODEL_H #define FRIEND_MODEL_H #include "user.hpp" #include

// フレンド関係操作インターフェース class FriendModel { public: // フレンド追加 void add(int userId, int friendId);

// フレンドリスト取得(JOINクエリ)
vector<User> getFriends(int userId);

};

#endif


**src/server/friendmodel.cpp**

#include "friendmodel.hpp" #include "db.h"

// フレンド追加処理 void FriendModel::add(int userId, int friendId) { // SQL生成 char sql[1024] = {0}; sprintf(sql, "INSERT INTO friend (userId, friendId) VALUES (%d, %d)", userId, friendId);

// DB実行
MySQL db;
if (db.connect())
{
    db.update(sql);
}

}

// フレンドリスト取得 vector<User> FriendModel::getFriends(int userId) { // クエリ作成 char sql[1024] = {0}; sprintf(sql, "SELECT a.id, a.name, a.status FROM user a INNER JOIN friend b ON b.friendId = a.id WHERE b.userId = %d", userId);

// 実行
MySQL db;
if (db.connect())
{
    MYSQL_RES *res = db.query(sql);
    if (res != nullptr)
    {
        // 結果解析
        MYSQL_ROW row;
        vector<User> userList;
        while ((row = mysql_fetch_row(res)) != nullptr)
        {
            User user;
            user.setId(atoi(row[0]));
            user.setName(row[1]);
            user.setStatus(row[2]);
            userList.push_back(user);
        }
        mysql_free_result(res);
        return userList;
    }
}
return vector<User>();

}


**include/server/chatservice.hpp**

#include "friendmodel.hpp"

// フレンド管理オブジェクト FriendModel _friendManager;


**src/server/chatservice.cpp**

// 処理バインディング

タグ: C++ muduo SQL クラスタサーバー JOINクエリ

8月4日 05:00 投稿