按思路來聊:
類似微信,點(diǎn)擊用戶可以進(jìn)入一對(duì)一聊天頁面;另有聊天框列表包含所有存在聊天記錄的一對(duì)一聊天框,點(diǎn)擊進(jìn)入聊天頁面。
【數(shù)據(jù)結(jié)構(gòu)】
因?yàn)殡p方都有聊天記錄,所以每一個(gè)聊天實(shí)際上得儲(chǔ)存兩份,設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)如下:
A :
1
|
user_a = {“ id ”: 1 ,”name”:”A”} |
B :
1
|
user_b = {“ id ”: 2 ,”name”:”B”} |
A的聊天記錄:
1
|
chat_a = { “ id ”: 1 , “user”: 1 , “who”: 2 , “name”:”B”, “new”: 0 , msg:[]} |
B的聊天記錄:
1
|
chat_b = { “ id ”: 2 , “user”: 2 , “who”: 1 , “name”:”A”, “new”: 0 , msg:[]} |
msg實(shí)際上是個(gè)list,結(jié)構(gòu)如下:msg = { “user”:發(fā)送者id, “name”:發(fā)送者name, “date”:發(fā)送時(shí)間, “content”:消息內(nèi)容 }
【業(yè)務(wù)邏輯】
當(dāng)A點(diǎn)擊好友列表中B的名字–>進(jìn)入聊天框(根據(jù)雙方id通過字段user、who找到對(duì)應(yīng)chat_a,chat = coll.find_one({“user”:user_a[‘id'], “who”:user_b[‘id']});如果該chat不存在,則利用雙方id創(chuàng)建chat_a)
發(fā)送消息(更新chat_a和chat_b,如果chat_b不存在則創(chuàng)建chat_b;如果chat_b不在線則更新chat_b[‘new'] = 1)
A刪除聊天框(刪除chat_a)
【記錄客戶端連接】
由于是多個(gè)一對(duì)一聊天,所以不能直接用教程里的set來記錄連接。
最后的決定是用一個(gè) dict,用雙方用戶id拼接的字符串作為key,用list存客戶端連接。
...SocketHandler(...):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
chats = dict () ... def on_open( self ): ... #通過雙方id來生成一個(gè)獨(dú)一無二的字符串 min = user_a[ 'id' ] max = user_b[ 'id' ] if min > max : max = user_a[ 'id' ] min = user_b[ 'id' ] key = str (user_a[ 'id' ]) + "_" + str (user_b[ 'id' ]) #判斷當(dāng)前會(huì)話是否存在,存在則添加當(dāng)前用戶 if key in chats: SocketHandler.chats[key].append( self ) #不存在則創(chuàng)建會(huì)話,并將當(dāng)前用戶添加進(jìn)去 else SocketHandler.chats[key] = [ self ] |
【發(fā)送消息】
從客戶端調(diào)用send函數(shù),在服務(wù)端on_message函數(shù)中接受參數(shù)后更新雙方聊天記錄。之后調(diào)用send_to_all(key, message)來更新聊天窗口。
【發(fā)通知/更新聊天窗口】
更新數(shù)據(jù)庫(kù)里的聊天記錄后還要在聊天窗口更新html,所以需要通知該會(huì)話的連接者。
根據(jù)我們記錄連接者的方式,對(duì)應(yīng)的通知函數(shù)如下:
1
2
3
|
def send_to_all(key,message): for user in SocketHandler.chats[key]: user.write_message(json.dumps(message)) |
【關(guān)閉連接】
根據(jù)我們記錄連接者的方式,對(duì)應(yīng)的關(guān)閉函數(shù)如下:
1
2
3
4
5
6
7
|
def on_close( self ): ... #用on_open函數(shù)中的方法構(gòu)造key if key in SocketHandler.chats: SocketHandler.chats[key].remove( self ) #刪除當(dāng)前連接 if len (SocketHandler.chats[key]) = = 0 : del SocketHandler.chats[key] #當(dāng)會(huì)話無連接者則刪除會(huì)話 |
經(jīng)過上面的改造,就實(shí)現(xiàn)多個(gè)一對(duì)一聊天功能