一、開發IM的同學建議空暇時間多去(即時通訊)官網看看相關資料,便于自己能更好的優化自己的邏輯
二、通篇文章在 https://blog.csdn.net/weixin_43487250/article/details/123767010??有書面詳細形式總結
三、下方總結是IM選型從那些方面考慮和調研(備注:下方涉及到的項目和demo等可以聯系樓主索要demo或者項目源碼)
自研發IM /繼承第三方研發IM整套架構設計
1.第三方形式,根據app業務,是否設計國內外以及不同的收費標準主流有七牛云,阿里百川,騰訊云,網易,融云,環信等多家主流三方,個人傾向網易和融云。
原因:
網易比較快速集成,各網站資料較多,容易借鑒。但后續帶寬服務收費較高。
融云也容易集成,但是SDK自帶UI和不帶UI的是兩套SDK,初始化方法差異性較大,但是融云的性能較好,對消息本息存儲做API的比較容易理解和調用
1.網易IM在(有完整項目)項目有完整體現,包含了視頻會議,群聊,群視頻音頻通話,閱后即焚,單聊,且支持所有聊天消息類型,圖文,語音,文本,視頻,群公告,群鏈接等
2.融云在(有完整項目)項目有體現,具體包含了聊天室功能,用以直播間的實時評論
以上兩種用法暫不闡述,可以再具體項目中學習以及可以參照官方開發文檔進行開發,但是其中的性能優化等整體優化方案需由開發者自行設計,學自研發IM的同學可以多下載第三方的demo,參照其整體架構模式設計有很好的的幫助
下面著重講一下自研發IM的方式
1.首先自研發IM,要對socket有一定的了解,畢竟IM是基于長連接的實現方式。
2.完成所有API設計后打包成SDK供上層開發同學使用,這里涉及到的SDK的設計思路和打包方法后續樓主其他文章可以查閱。
1.socket的選型有socket,websocket,對兩種方式要有所了解
套接字(Socket)是通信的基石,是支持TCP/IP協議的網絡通信的基本操作單元。它是網絡通信過程中端點的抽象表示,包含進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
應用層通過傳輸層進行數據通信時,TCP會遇到同時為多個應用程序進程提供并發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個TCP協議端口傳輸數據。為了區別不同的應用程序進程和連接,許多計算機操作系統為應用程序與TCP/IP協議交互提供了套接字(Socket)接口。應用層可以和傳輸層通過Socket接口,區分來自不同應用程序進程或網絡連接的通信,實現數據傳輸的并發服務。
ok,看到這里還有蒙圈的同學,大抵是對網絡的七層協議理解的有所遺忘,所以回過頭需要把網絡的七層協議都了解一下方便知道每一層是如何工作的
OSI的7層從上到下分別是7應用層6表示層5會話層4傳輸層3網絡層2數據鏈路層1物理層;其中高層(即7、6、5、4層)定義了應用程序的功能,下面3層(即3、2、1層)主要面向通過網絡的端到端,點到點的數據流。
參考文檔:https://baike.baidu.com/item/網絡七層協議/6056879?fr=aladdin,通讀文檔可以理解,高層是通過底層的接口來實現交互,低層也可以理解為我們ios的api底層,他只需要誰調用他時候,傳來參數即可,至于底層的實現協議和算法無需高層考慮,那么低層從高層就很好理解了,電信號,電流等表示物理層,光纖傳輸鏈路則為數據鏈路層,路由則為網絡層,而我們的tcp和udp就是傳輸層了,消息數據的傳遞就是會話層,數據的處理就是表示層,最后統一到底應用程序,就是應用層了。
而我們需要重點關注的是代碼配置方向的層面,物理層,鏈路層,會話層是不需要我們重點關注的,都是由硬件決定,軟件決定的范圍只有 應用層+會話層+傳輸層。
Tcp和UDP區別:
https://www.xinnet.com/xinzhi/65/118739.html
選型參考:
http://www.52im.net/thread-33-1-1.html?https://blog.csdn.net/qq_21521371/article/details/81199071?https://zhidao.baidu.com/question/563196162991295124.html
通過以上文章分析,目前我們采用TCP協議進行傳輸
可以揣測到微信是基于TCP的鏈接,部分采用UDP傳輸,部分采用TCP傳輸應該
3.下面就開始我們的套接字的選型了,套接字分為Socket和websocket,二者的區別
參考:https://blog.csdn.net/qushaming/article/details/90747326
?? ? ? ? https://www.cnblogs.com/barrywxx/p/7412808.html
webSocket是基于http短連接,輪詢,長輪詢之后誕生的基于http協議的應用層協議的一層協議,其是通過http建立連接,但是也是基于TCP協議傳輸,它必須依賴?HTTP 協議進行一次握手?,握手成功后,數據就直接從 TCP 通道傳輸,與 HTTP 無關了。而socket是基于數據傳輸層的協議,是虛擬出來的一層,可以理解為傳輸層和表示層中間的一種接口協議
4.iOS平臺有哪些WebSocket和Socket的開源框架
Socket開源框架有:CocoaAsyncSocket,socketio/socket.io-client-swift
WebSocket開源框架有:facebook/SocketRocket,tidwall/SwiftWebSocket
OK到這里 webSocket的底層連接方法
開頭的鏈接中,將這些方法封裝在你自己的SDK中,并對數據進行處理,如存儲,加密,前后端定義好,并遵循SDK設計原則,將上層對接的同學需要的業務曝露在自己的API里面
5.單機最大的tcp連接數可以參考http://www.52im.net/thread-561-1-1.html,做單機垂直負載擴展的優化,然后在考慮分布負載的水平優化,做到最大限度的服務器優化
socket開發方式:
參考資料:http://www.lxweimin.com/p/0a11b2d0f4ae
下面說一下IM自研發/非自研發的整體架構可參考https://codingdict.com/os/software/65233?
1.所有點h合集的目標文件(類似PCH)CDChatList
2消息類型API CDChatListProtocols?
可以包含任何你想暴露出來的代理方法,屬性,枚舉
如:
typedef enum : NSUInteger {
? ? CDMessageTypeText,? ? ? //文字類型0
? ? CDMessageTypeImage,? ? //圖片類型1
? ? CDMessageTypeAudio,? ? //音頻類型2
? ? CDMessageTypeSystemInfo,//系統信息類型3
? ? CDMessageTypeVIDEO,? ? ? //視頻類型
? ? CDMessageTypeDING,? ? //視頻類型
? ? CDMessageTypeLocation,? //位置類型
? ? CDMessageTypeFile,? //文檔類型
? ? CDMessageTypeBig,//點贊大表情
? ? CDMessageTypeCancel,//撤回
? ? CDMessageTypeTouch,? // @類型
? ? CDMessageTypeReply,? //回復
? ? CDMessageTypeVoiceToText,//語音轉文字
? ? CDMessageTypeGroupAnn,//群公告
? ? CDMessageTypeBusinessCard,? //名片
? ? CDMessageTypeMeeting,? //會議消息
? ? CDMessageTypeVoiceWithVideo,//? 語音視頻
} CDMessageType;//消息類型
typedef enum : NSUInteger {
? ? CDMessageStateNormal,
?? ?CDMessageStateSending,? ? ? ? ? //圖片消息上傳中/文字消息發送中
? ? CDMessageStateSendFaild,? ? ? ? //消息發送失敗
? ? CDMessageStateDownloading,? ? ? //圖片消息下載中
? ? CDMessageStateDownloadFaild? ? //圖片消息下載失敗
} CDMessageState;
3.每一個大的功能既然都有單獨的一個單例類來管理,其涉及到的點擊事件也要單獨放在這個管理類里面,且要用多級代理的方式最終將點擊事件的具體實現引入到CDViewController.h層級中
目的:
1.便于管理,修改和維護
2.便于VC之間的交互,跳轉,數據傳遞等
如:CTMoreKeyBoard文件中的點擊事件
4.優化點:1.CTTextView文件中 textView設置為不可滾動,防止輸入跳動,則其高度根據輸入文字以及間距實時監聽并計算,修改其高度
5.以前微信一條消息的長按 會有兩種方式,1.長按出現復制,轉發等彈出框,一邊長按一邊橫向滑動會出現放大鏡,
那么 長按? 和長按橫向拖動 會有兩種彈出視圖切換,如何檢測
currentMode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain());
? ? ? ? self.backgroundColor =[UIColor clearColor];
? ? ? ? _selectionStartPosition = 5;
? ? ? ? _selectionEndPosition = 1;
? ? ? ? [self setupGestures];
? ? ? ? __weak __typeof(self)weakSelf = self;
? ? ? ? CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault,kCFRunLoopAllActivities,YES,0,^(CFRunLoopObserverRef observer,CFRunLoopActivity activity){
? ? ? ? ? ? __strong __typeof(weakSelf)strongSelf = weakSelf;
? ? ? ? ? ? if(strongSelf==nil){
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? CFComparisonResult rest = CFStringCompare(strongSelf->currentMode,CFRunLoopCopyCurrentMode(CFRunLoopGetMain()),kCFCompareBackwards);
? ? ? ? ? ? if(rest != kCFCompareEqualTo){
? ? ? ? ? ? ? ? strongSelf->currentMode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain());
? ? ? ? ? ? ? ? if((NSString *)CFBridgingRelease(strongSelf->currentMode)== UITrackingRunLoopMode){
? ? ? ? ? ? ? ? ? ? [strongSelf scrollDidScroll];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? CFRunLoopAddObserver(CFRunLoopGetMain(),observer,kCFRunLoopCommonModes);
所以可以通過CFRunLoopObserverRef監聽,通過UITrackingRunLoopMode對比來處理拖動事件
5.coreText? 做IM的圖形排版,圖文混排的優勢
https://www.pianshen.com/article/41191695402/
6.新消息進來時候,更新的是消息列表的數據源,并更新整個tableView的總高,這里更新總高的時候,舊消息的高度是在消息模型中有存儲,而新消息的高度計算后并進行存儲,新消息的計算方式優化到coreText的排版引擎,并提前將文本內容進行渲染,而新消息的展示則直接在tableView的底部插入最新一行,不需要整體刷新,并且某一條數據若是出現不及時,卡頓時候需要用dispaycell進行預渲染刷新處理。
如何實現安全?
在SDK與服務器的連接建立過程中有一個復雜的秘鑰協商過程,首先客戶端需要生成一個一次性使用的加密秘鑰,并使用非對稱加密方式將這個秘鑰加密之后傳給服務器,加密數據會被服務器解密,之后該加密秘鑰被保留在該長連接的會話信息中,數據來往均使用該秘鑰加密,這是一個流式加密,可以有效防止中間人攻擊和數據包回放等攻擊手段。