[CareerCup] 8.7 Chat Server 聊天服務器

8.7 Explain how you would design a chat server. In particular, provide details about the various backend components, classes, and methods. What would be the hardest problems to solve?

這個簡易的聊天服務器功能十分的有限,畢竟只是針對面試題的,誰也無法在面試的有限時間內設計出像QQ那樣強大的聊天工具,所以只是實現一些基本的功能即可,根據書上所述,包括如下功能:

1. 登陸和登出

2. 添加請求(發送,接受,和拒絕)

3. 更顯一個狀態消息

4. 建立私聊和群聊

5. 添加信息到私聊和群聊

enum UserStatusType { Offline, Away, Idle, Available, Busy };
enum RequestStatus { Unread, Read, Accepted, Rejected };class Date {
public:Date() {}Date(int m, int d, int y): _month(m), _day(d), _year(y) {}private:int _month, _day, _year;
};class Message {
public:Message(string content, Date *date): _content(content), _date(date) {} string getContent() { return _content; }Date* getDate() { return _date; }private:string _content;Date *_date;
};class Conversation {
public:vector<Message*> getMessages() { return _messages; }bool addMessage(Message *m) { _messages.push_back(m);return true;} int getId() { return _id; }protected:vector<User*> _participants;int _id;vector<Message*> _messages;
};class GroupChat: public Conversation {
public:void removeParticipant(User *user) {for (vector<User*>::iterator it = _participants.begin(); it != _participants.end(); ++it) {if (*it == user) _participants.erase(it);}} void addParticipant(User *user) {_participants.push_back(user);} 
};class PrivateChat: public Conversation {
public:PrivateChat(User *user1, User *user2) {_participants.push_back(user1);_participants.push_back(user2);} User* getOtherParticipant(User *primary) {if (_participants[0] == primary) {return _participants[1];} else if (_participants[1] == primary) {return _participants[0];}return nullptr;} 
};class AddRequest {
public:AddRequest(User *from, User *to, Date *date): _fromUser(from), _toUser(to), _date(date) {_status = RequestStatus::Unread;} void setStatus(RequestStatus status) { _status = status; }RequestStatus getStatus() { return _status; }User* getFromUser() { return _fromUser; }User* getToUser() { return _toUser; }Date* getDate() { return _date; }private:User *_fromUser;User *_toUser;Date *_date;RequestStatus _status;
};class UserStatus{
public:UserStatus(UserStatusType type, string message): _type(type), _message(message) {} UserStatusType getStatusType() { return _type; }string getMessage() { return _message; }private:string _message;UserStatusType _type;
};class UserManager;class User {
public:User(int id, string accountName, string fullName): _id(id), _accountName(accountName), _fullName(fullName) {}bool sendMessageToUser(User *to, string content) {PrivateChat *chat = _privateChats[to->getId()];if (chat == nullptr) {chat = new PrivateChat(this, to);_privateChats[to->getId()] = chat;}Message *message = new Message(content, new Date());return chat->addMessage(message);} bool sendMessageToGroupChat(int id, string content) {GroupChat *chat = _groupChats[id];if (chat != nullptr) {Message *message = new Message(content, new Date());return chat->addMessage(message);}return false;} void setStatus(UserStatus *status) { _status = status; }UserStatus* getStatus() { return _status; };bool addContact(User *user) {if (_contacts.find(user->getId()) != _contacts.end()) {return false;} else {_contacts[user->getId()] = user;return true;}} void receivedAddRequest(AddRequest *req) {int senderId = req->getFromUser()->getId();if (_receivedAddRequests.find(senderId) == _receivedAddRequests.end()) {_receivedAddRequests[senderId] = req;}} void sentAddRequest(AddRequest *req) {int receiverId = req->getFromUser()->getId();if (_sentAddRequests.find(receiverId) == _sentAddRequests.end()) {_sentAddRequests[receiverId] = req;}} void removeAddRequest(AddRequest *req) {if (req->getToUser() == this) {for (unordered_map<int, AddRequest*>::iterator it = _receivedAddRequests.begin(); it != _receivedAddRequests.end(); ++it) {if (it->second == req) _receivedAddRequests.erase(it);}} else if (req->getFromUser() == this) {for (unordered_map<int, AddRequest*>::iterator it = _sentAddRequests.begin(); it != _sentAddRequests.end(); ++it) {if (it->second == req) _sentAddRequests.erase(it);}}} void requestAddUser(string accountName) {UserManager::getInstance()->addUser(this, accountName);} void addConversation(PrivateChat *conversation) {User *otherUser = conversation->getOtherParticipant(this);_privateChats[otherUser->getId()] = conversation;}void addConversation(GroupChat *conversation) {_groupChats.push_back(conversation);}int getId() { return _id; }string getAccountName() { return _accountName; };string getFullName() { return _fullName; }private:int _id;UserStatus *_status = nullptr;unordered_map<int, PrivateChat*> _privateChats;vector<GroupChat*> _groupChats;unordered_map<int, AddRequest*> _receivedAddRequests;unordered_map<int, AddRequest*> _sentAddRequests;unordered_map<int, User*> _contacts;string _accountName;string _fullName;
};
class UserManager {
public:static UserManager* getInstance() {if (_instance == nullptr) _instance = new UserManager();return _instance;}void addUser(User *fromUser, string toAcountName) {User *toUser = _usersByAccountName[toAcountName];AddRequest *req = new AddRequest(fromUser, toUser, new Date());toUser->receivedAddRequest(req);fromUser->sentAddRequest(req);} void approveAddRequest(AddRequest *req) {req->setStatus(RequestStatus::Accepted);User *from = req->getFromUser();User *to = req->getToUser();from->addContact(to);to->addContact(from);} void rejectAddRequest(AddRequest *req) {req->setStatus(RequestStatus::Rejected);User *from = req->getFromUser();User *to = req->getToUser();from->removeAddRequest(req);to->removeAddRequest(req);}void userSignedOn(string accountName) {User *user = _usersByAccountName[accountName];if (user != nullptr) {user->setStatus(new UserStatus(UserStatusType::Available, ""));_onlineUsers[user->getId()] = user;}} void userSignedOff(string accountName) {User *user = _usersByAccountName[accountName];if (user != nullptr) {user->setStatus(new UserStatus(UserStatusType::Offline, ""));for (unordered_map<int, User*>::iterator it = _onlineUsers.begin(); it != _onlineUsers.end(); ++it) {if (it->first == user->getId()) _onlineUsers.erase(it);}}} 
private:static UserManager *_instance;unordered_map<int, User*> _usersById;unordered_map<string, User*> _usersByAccountName;unordered_map<int, User*> _onlineUsers;
};

本文轉自博客園Grandyang的博客,原文鏈接:聊天服務器[CareerCup] 8.7 Chat Server ,如需轉載請自行聯系原博主。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392102.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392102.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392102.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

react hooks使用_如何開始使用React Hooks:受控表格

react hooks使用by Kevin Okeh由Kevin Okeh 如何開始使用React Hooks&#xff1a;受控表格 (How to Get Started With React Hooks: Controlled Forms) React Hooks are a shiny new proposal that will allow you to write 90% cleaner React. According to Dan Abramov, Hoo…

特征工程tf-idf_特征工程-保留和刪除的內容

特征工程tf-idfThe next step after exploring the patterns in data is feature engineering. Any operation performed on the features/columns which could help us in making a prediction from the data could be termed as Feature Engineering. This would include the…

c語言定義數組a10 指定各元素,C語言填空題.doc

C語言填空題.doc二、填空題1、C 語言只有 32 個關鍵字和 9 種控制語句。2、每個源程序有且只有一個 main 函數&#xff0c;系統總是從該函數開始執行 C 語言程序。 3、C 語言程序的注釋可以出現在程序中的任何地方&#xff0c;它總是以 * 符號作為開始標記&#xff0c;以 */ 符…

貓狗隊列

功能要求&#xff1a; 用戶可以調用push方法將cat類或dog類的實例放入隊列中;用戶可以調用pollAll方法&#xff0c;將隊列中所有的實例按照進隊列的先后順序依次彈出;用戶可以調用pollDog方法&#xff0c;將隊列中dog類的實例按照進隊列的先后順序依次彈出;用戶可以調用pollCat…

如何使用HTML5,JavaScript和Bootstrap構建自定義文件上傳器

by Prashant Yadav通過Prashant Yadav 如何使用HTML5&#xff0c;JavaScript和Bootstrap構建自定義文件上傳器 (How to build a custom file uploader with HTML5, JavaScript, & Bootstrap) In this short article, we’ll learn how to create custom file uploader wit…

monkey測試===通過monkey測試檢查app內存泄漏和cpu占用

最近一直在研究monkey測試。網上資料很多&#xff0c;但都是一個抄一個的。原創的很少 我把檢查app內存泄漏的情況梳理一下&#xff1a; 參考資料&#xff1a; Monkey測試策略&#xff1a;https://testerhome.com/topics/597 Android Monkey測試詳細介紹&#xff1a;http://www…

數據挖掘—主成分分析法降維和最小最大規范化

算法步驟:1)將原始數據按列組成n行m列矩陣X2)特征中心化。即每一維的數據都減去該維的均值&#xff0c;使每一維的均值都為03)求出協方差矩陣4)求出協方差矩陣的特征值及對應的特征向量5)將特征向量按對應的特征值大小從上往下按行排列成矩陣&#xff0c;取前k行組成矩陣p6)YPX…

用戶使用說明c語言,(C語言使用指南.docx

(C語言使用指南Turbo C(V2.0)使用指南(本文的許多命令或方法同樣適用于TC3) 在開始看本文以前&#xff0c;我先說明一下C語言的安裝和使用中最應該注意的地方&#xff1a;許多網友在下載Turbo C 2.0和Turbo C 3.0后&#xff0c;向我問得最多的是在使用過程中碰到如下問題&…

三維空間兩直線/線段最短距離、線段計算算法 【轉】

https://segmentfault.com/a/1190000006111226d(ls,lt)|sj?tj||s0?t0(be?cd)u? ?(ae?bd)v? ac?bd(ls,lt)|sj?tj||s0?t0(be?cd)u? ?(ae?bd)v? ac?b2|具體實現代碼如下&#xff08;C#實現&#xff09;&#xff1a; public bool IsEqual(double d1, double d2) { …

【慎思堂】之JS牛腩總結

一 JS基礎 1-定義 Javascript是一種腳本語言/描述語言&#xff0c;是一種解釋性語言。用于開發交互式web網頁&#xff0c;使得網頁和用戶之間實現了一種實時性的、動態的、交互性的關系&#xff0c;使網頁包含更多活躍的元素和更加精彩的內容。 主要用于&#xff1a;表單驗證 …

vuejs 輪播_如何在VueJS中設計和構建輪播功能

vuejs 輪播by Fabian Hinsenkamp由Fabian Hinsenkamp設計 A carousel, slideshow, or slider — however you call it this class of UI — has become one of the core elements used in modern web development. Today, it’s almost impossible to find any Website or UI …

iOS繪圓形圖-CGContextAddArc各參數說明

2019獨角獸企業重金招聘Python工程師標準>>> 1.使用 UIGraphicsGetCurrentContext() 畫圓 CGContextAddArc(<#CGContextRef _Nullable c#>, <#CGFloat x#>, <#CGFloat y#>, <#CGFloat radius#>, <#CGFloat startAngle#>, <#CGFlo…

c語言中if和goto的用法,C語言中if和goto的用法.doc

C語言中if和goto的用法C語言中&#xff0c;if是一個條件語句&#xff0c;用法??if(條件表達式) 語句如果滿足括號里面表達式&#xff0c;表示邏輯為真于是執行后面的語句&#xff0c;否則不執行(表達式為真則此表達式的值不為0&#xff0c;為假則為0&#xff0c;也就是說&…

數據挖掘—K-Means算法(Java實現)

算法描述 &#xff08;1&#xff09;任意選擇k個數據對象作為初始聚類中心 &#xff08;2&#xff09;根據簇中對象的平均值&#xff0c;將每個對象賦給最類似的簇 &#xff08;3&#xff09;更新簇的平均值&#xff0c;即計算每個對象簇中對象的平均值 &#xff08;4&#xf…

自我價值感缺失的表現_不同類型的缺失價值觀和應對方法

自我價值感缺失的表現Before handling the missing values, we must know what all possible types of it exists in the data science world. Basically there are 3 types to be found everywhere on the web, but in some of the core research papers there is one more ty…

[收藏轉載]C# GDI+ 簡單繪圖(一)

最近對GDI這個東西接觸的比較多&#xff0c;也做了些簡單的實例&#xff0c;比如繪圖板&#xff0c;仿QQ截圖等&#xff0e; 廢話不多說了&#xff0c;我們先來認識一下這個GDI&#xff0c;看看它到底長什么樣. GDI&#xff1a;Graphics Device Interface Plus也就是圖形設備接…

mybaties總結+hibernate總結

一、對原生態jdbc程序中問題總結 1.1 jdbc程序 需求&#xff1a;使用jdbc查詢mysql數據庫中用戶表的記錄 statement:向數據庫中發送一個sql語句 預編譯statement&#xff1a;好處&#xff1a;提高數據庫性能。 預編譯statement向數據庫中發送一個sql語句&#xff0c;數據庫編譯…

客戶旅程_我如何充分利用freeCodeCamp的旅程

客戶旅程by Catherine Vassant (aka Codingk8)由凱瑟琳瓦森(Catherine Vassant)(又名Codingk8) 我如何充分利用freeCodeCamp的旅程 (How I made the most out of my freeCodeCamp journey) 我的路線圖&#xff1f; ?超越課程范圍的reeCodeCamp (My road map ?? to freeCode…

Python14 函數

函數 面向對象編程&#xff1a; 類----class 面向過程編程&#xff1a;過程---def 函數式編程&#xff1a;函數---def def test(x):描述x 1return x#def是定義函數的關鍵字#test是函數名稱#&#xff08;x&#xff09;是參數#x1是 函數體&#xff0c;是一段邏輯代碼#return 定義…

學習sql注入:猜測數據庫_面向數據科學家SQL:學習簡單方法

學習sql注入:猜測數據庫We don’t pick a hammer and look for nails — that would be an unusual way of solving problems. The usual way of doing business is to identify the problem first, then look for appropriate tools.我們不用錘子找釘子&#xff0c;那是解決問…