今天開始講解即時聊天室的0.0.3版,想了解上一篇文章的朋友們可查看即時聊天室開發曆程-0.0.2版
基于上個版本的最後規劃,這個版本是要将聊天内容對應的賬号也顯示出來的。先上2張效果圖
以上2張圖顯示了test和abc123賬号以及對應的聊天内容,那麼是怎麼實現的呢?下面就來講下相關的實現。
先講講實現思路。之前是通過websocket協議純粹的發送和廣播一下聊天内容,就是發送和廣播一段字符串。現在聊天内容前面要加上賬号的顯示,那麼這段要發送的字符串就要改為帶上發送者的賬号發送給服務端,然後服務端再把聊天内容和對應的賬号再一起廣播給所有在線用戶。
确定了思路之後,再看看具體要怎麼處理。如果是發送一段純粹的字符串,那麼怎麼解析呢?于是乎,我想到了使用json來編碼字符串。另外前端目前沒有發送者的賬号,那咋辦呢?其實不要緊,用戶在登錄成功的時候,前端已經存下了一個登錄令牌,前端發送登錄令牌來代替發送者的賬号也是可以的。一般的項目開發,也都是用發送登錄令牌來代替要發送的用戶信息,這樣既減輕前端存儲用戶信息的壓力,也保證了用戶信息的安全性。
讓我們一起來看看前端發送聊天内容的代碼變化
send(){
let u_token = uni.getStorageSync('u_token');
if (u_token != '') {
this.sendSocketMessage(JSON.stringify({
'token':u_token,
'send_data':this.send_data
}));
} else {
this.inputDialogToggle();
}
}
我們看到要向服務端發送的數據已經使用了json編碼了,并且看到其中一個要發送的參數就是使用了存儲好的登錄令牌u_token
this.sendSocketMessage(JSON.stringify({
'token':u_token,
'send_data':this.send_data
}));
然後我們一起看看服務器接收到前端發送的數據是怎麼處理的,做了哪些改變
if ($frame->data != 'alive') {
$list = json_decode($frame->data, true);
$user_token = new UserTokenModel();
$user_token_result = $user_token->get([
'token' => $list['token']
]);
if ($user_token_result === NULL) {
$server->push($frame->fd, json_encode([
'code' => -1,
'msg' => '未登錄'
]));
} else {
$user_token_result = $user_token_result->toArray();
$user = new UserModel();
$user_result = $user->get([
'id' => $user_token_result['user_id']
]);
$user_result = $user_result->toArray();
foreach($server->table as $row)
{
$server->push($row['fd'], json_encode([
'code' => 1,
'data' => [
'account' => $user_result['account'],
'content' => $list['send_data']
]
]));
}
}
}
接下來我講以上代碼逐段講解
1.我們看到,if ($frame->data != 'alive'),這段代碼首先去掉了來自心跳的信息處理
2.$list = json_decode($frame->data, true);,這段代碼對來自前端的json編碼的字符串進行解碼
3.取出登錄用戶信息,代碼如下
$user_token_result = $user_token->get([
'token' => $list['token']
]);
4.判斷下用戶有沒有處于登錄狀态
if ($user_token_result === NULL)
未登錄時,直接返回“未登錄”描述信息,返回的代碼也做了json編碼,代碼如下
$server->push($frame->fd, json_encode([
'code' => -1,
'msg' => '未登錄'
]));
5.處于登錄狀态時取出用戶賬号信息,代碼如下
$user_result = $user->get([
'id' => $user_token_result['user_id']
]);
6.将聊天内容以及對應賬号廣播給所有在線用戶,返回數據也進行json編碼
foreach($server->table as $row)
{
$server->push($row['fd'], json_encode([
'code' => 1,
'data' => [
'account' => $user_result['account'],
'content' => $list['send_data']
]
]));
}
接下來我們看看前端接收到後端返回的數據是如何處理的
uni.onSocketMessage(function (res) {
let obj = JSON.parse(res.data);
if (obj.code == 1) {
let key = uni.getStorageSync('extraLine');
key = key obj.data.account ':' obj.data.content '\n';
that.title = key;
uni.setStorageSync('extraLine', key);
} else {
console.log(obj.msg);
}
});
接下來繼續對以上代碼逐端講解
1.let obj = JSON.parse(res.data);,這段代碼對接收到的數據進行json解碼
2.if (obj.code == 1),判斷一下後端返回的狀态是否為1,1代表成功,不成功就打印一下不成功的信息console.log(obj.msg);
3.key = key obj.data.account ':' obj.data.content '\n';對收到的賬号和聊天内容拼接處理,以後也可以擴展為賬号單獨處理為鍊接
講完了細節,接下來再講講延申,大家也可以先消化下再往下看。
一.通過之前的講解,大家可能會注意到有時候我會使用websocket協議,有時候我會使用http協議,那麼這2種協議應該怎麼選擇呢?這個需要了解2種協議的一些差異之處。http協議的模式是一問一答,即客戶端請求服務端響應。而websocket則是全雙工模式,不僅支持客戶端請求服務端響應,而且服務端還能主動向客戶端發送數據。也就是當需要服務端主動向客戶端發送數據時,使用http協議做不到,那麼就可以考慮使用websocket協議,比如要做到廣播。
二.大家可能會注意到目前我的講解總是講變化後的情況,并沒有對比上一個版本的演化。這裡我決定對項目代碼增加版本管理,選擇git。
選擇了git就要使用git的服務端和客戶端。
首先講git服務端
1.使用第3方托管方式的git服務端,這種方式缺點在安全性不高,還有功能比較受限,優點在不用搭建git服務端
2.自行搭建簡單git協議服務端,這種方式隻适合小團隊
3.自行搭建http協議服務端
4.自行搭建gitlab,這種方式适合有規模的團隊
然後講git客戶端
我個人喜歡安裝git客戶端的同時多安裝一個git圖形化客戶端,這類軟件非常多,我選擇了烏龜git。原因是git圖形化客戶端功能一般更強大,更适合開發。
最後再規劃一下下個版本,下個版本我打算增加後台頁面,對聊天内容進行維護管理。
,