時序圖
登錄轿塔,密鑰交換流程:
Paste_Image.png
如果重連返回的結果失敗,可能是因為服務器重啟或會話已過期造成的,則需要重頭開始用帳號密碼請求登錄勾缭。
用戶界面聊天流程:
Paste_Image.png
消息列表的實時更新流程類似2揍障,要先訂閱allNewMessage
協(xié)議和接口:
統(tǒng)一采用json文本形式,utf-8編碼后傳輸俩由。
json對象必須包含head屬性
作為固定接口的秒數毒嫡,data屬性
指明傳輸的參數數據,data屬性的數據類型可能為單一類型(字符串采驻、數字审胚,布爾型用1和0替代),也可能是一個對象或數組礼旅。
關于加密
- 雙方用登錄時交換的des對稱性密鑰進行加解密
- 加密的接口要附加
secret
屬性膳叨,設置值為1,接收方根據該屬性判斷是否需要解密 - 只對data的json字符串加密痘系,在用base64編碼成可傳輸的字符串菲嘴,最終的json對象效果如下:
{
head:{
action: "actionName",
secret: 1
} ,
data: "base64 string"
} - 目前只需要對帶有聊天內容的data加密
登錄請求
- 方向:客戶端 >> 服務端
- 內容:
JSON
(注意下面只是解析后的對象,并非實際傳輸的JSON字符串
):
{
head: {
action: "login"
},
data: {
userId:"ksoeufjgkwqoeitkdjgkdlgpekfjdlgd",
password:"KDSJEHWKR"
}
} - 說明:必須在建立socket連接后3秒內發(fā)送汰翠,否則服務端將自動關閉
socket連接
龄坪,掉線后需要重新建立連接。
登錄確認結果
- 方向:服務端 >> 客戶端
- 內容:
{
action: "loginRes",
data:
{
result:1, // 1成功 2 密碼驗證失敗 3 密鑰驗證失敻椿健(可能服務器重啟導致所有會話丟失)
key:"rsa公鑰"
}
} - 說明:rsa公鑰用于加密客戶端發(fā)給服務端的des密鑰健田,des密鑰用于敏感的數據加密解密,如聊天消息佛纫。如果是重連妓局,則不包含key
客戶端密鑰
- 方向:客戶端 >> 服務端
- 內容:
{
action: "secretKey",
data:"加密過的des密鑰" // 加密過的des密鑰
} - 說明:保留該加密過的des密鑰,還可以用來重新快速登錄
心跳通知
- 方向:客戶端 >> 服務端
- 內容:
{
action:"keepAlive"
} - 如果掉線呈宇,服務端保留最多一小時的訂閱狀態(tài)和密鑰好爬,在一小時內realive即可快速恢復,否則需要重頭登錄和訂閱甥啄。
重新快速登錄
- 方向:客戶端 >> 服務端
- 內容:
{
action: "realive",
data:"剛才加密過的des密鑰" // 剛才加密過的des密鑰
} - 返回接口
loginResult
存炮,如果驗證失敗,則要重頭開始登錄和訂閱(服務器會話丟失)
發(fā)送聊天消息
方向:客戶端 >> 服務端
內容:
{
action:"sendMessage",
data:{
id: 3939393939, // 消息ID蜈漓,整型(客戶端生成:時間毫秒值*10000+隨機數(0~9999)組合)
receiver: "ksoeufjgkwqoeitkdjgkdlgpekfjdlgd", // 目標用戶ID
type: 0, // 0 默認為文本穆桂,1為圖片
content:""http:// 如果是圖片,則內容為圖片縮略圖的URL
fileSuffix: ".txt", // 如果是圖片融虽,則必須有該屬性充尉,文件后綴名包含.點號
fileSource: "", // 如果是圖片,則必須有該屬性衣形,高清圖的地址
}
}說明:圖片要預先上傳到七牛,七牛的key格式為:
/im/{userId}/{message id}
發(fā)送聊天消息結果
- 方向:服務端 >> 客戶端
- 內容:
{
action: "sendMessageResult",
data: {
id: 3939393939, // 消息ID,這個是客戶端生成的ID
type: 1 // 表示已被服務器接收谆吴,但還未轉發(fā)給目標用戶倒源,2表示已被目標用戶接收
}
}
訂閱實時消息
- 方向:客戶端 >> 服務端
- 內容:
{
action: "subscribe"
data: {
type: "userMessage", // userNewMessage | allNewMessage
target: "用戶ID" // 如果是userMessage,則顯示是該用戶ID
}
}
訂閱實時消息成功
- 方向:服務端 >> 客戶端
- 內容:
{
action: "subscribeSuccess",
data: {
type: "userMessage", // userNewMessage | allNewMessage
target: "用戶ID" // 如果是userMessage句狼,則顯示是該用戶ID
}
}
取消訂閱消息
- 方向:客戶端 >> 服務端
- 內容:
{
action: "unsubscribe"
data: {
type: "userMessage", // userNewMessage | allNewMessage
target: "用戶ID" // 如果是userMessage笋熬,該參數是必須的
}
}
取消訂閱實時消息成功
- 方向:服務端 >> 客戶端
- 內容:
{
action: "unsubscribeSuccess",
data: {
type: "userMessage", // userNewMessage | allNewMessage
target: "用戶ID" // 如果是userMessage,則顯示是該用戶ID
}
}
請求聊天記錄
- 方向:客戶端 >> 服務端
- 內容:
{
action: "requestChatHistory",
data:{
userId: "目標用戶ID",
endTime: "截至時間(不包含)", // 默認當前時間
beginTime: "初始時間(包含)", // 可為空
maxRecord: 50, // 默認50條最新記錄
}
}
接收歷史消息
- 方向:服務端 >> 客戶端
- 內容:
{
action: "receiveChatHistory",
data:[{
sender: "發(fā)送人的用戶ID",
id: 3939393939, // 消息ID腻菇,整型(客戶端生成:時間毫秒值*10000+隨機數(0~9999)組合)
type: 0, // 0 默認為文本胳螟,1為圖片
content:""http:// 如果是圖片,則內容為圖片縮略圖的URL
fileSuffix: ".txt", // 如果是圖片筹吐,則必須有該屬性糖耸,文件后綴名包含.點號
fileSource: "", // 如果是圖片,則必須有該屬性丘薛,高清圖的地址
read:1, // 是否已讀嘉竟,已讀
}]
}
實時接收未讀消息(聊天界面)(需要訂閱)
- 方向:服務端 >> 客戶端
- 內容:
{
action:"receiveUserNewMessage",
data:{
sender: "ksoeufjgkwqoeitkdjgkdlgpekfjdlgd", // 發(fā)送者用戶ID
list: [{
id: 3939393939, // 消息ID,整型(客戶端生成:時間毫秒值*10000+隨機數(0~9999)組合)
type: 0, // 0 默認為文本洋侨,1為圖片
content:""http:// 如果是圖片舍扰,則內容為圖片縮略圖的URL
fileSuffix: ".txt", // 如果是圖片,則必須有該屬性希坚,文件后綴名包含.點號
fileSource: "", // 如果是圖片边苹,則必須有該屬性,高清圖的地址
}, ....]
}
}
實時接收新消息的簡要(消息列表)(需要訂閱)
- 方向:服務端 >> 客戶端
- 內容:
{
action: "receiveAllNewMessage",
data:[
{
sender: {
userName: "用戶名"裁僧,
headImg: "頭像",
userId: "用戶ID"
},
newest: {
id: 3939393939, // 消息ID个束,整型(客戶端生成:時間毫秒值*10000+隨機數(0~9999)組合)
type: 0, // 0 默認為文本,1為圖片
content:""http:// 如果是圖片锅知,只顯示【圖片】播急,如果文本過長,會自動截斷最多50個字符
}, // 最新一條消息
unread: 10, // 累計未讀消息總數
},....]
}
實時接收用戶在線狀態(tài)
- 方向:服務端 >> 客戶端
- 內容:
{
action: "receiveUserState",
data:{
userId: "",
userName: "",
headImg, "",
online: 1, // 在線售睹,0不在線
}
}
發(fā)送未讀消息接收成功
- 方向:服務端 >> 客戶端
- 內容:
{
action: "sendReadMessageSuccess",
data: [3939393939,...] // 消息ID數組
}