個人博客:haichenyi.com桐款。感謝關(guān)注
1. 目錄
2. 概念
??首先,需要確定的就是他們是socket通信的兩種協(xié)議魔眨。
??TCP:一種面向連接,全雙工可靠信道的傳輸層協(xié)議
??UDP:一種無連接的遏暴,不可靠的傳輸層協(xié)議
3. 優(yōu)缺點
類型 | 安全 | 有序 | 速度 | 對象個數(shù) | 開銷 | 方式 |
---|---|---|---|---|---|---|
TCP | 安全 | 有序 | 慢 | 1:1 | 大 | 面向字節(jié)流 |
UDP | 不安全 | 無序 | 快 | 1:1,1:N朋凉,N:N,N:1 | 小 | 面向報文 |
是否安全:TCP是采用的全雙工可靠信道杂彭,很安全。UDP采用得是不可靠得傳輸協(xié)議
是否有序:TCP:有序亲怠,一個傳完下一個才能繼續(xù)。UDP:無序团秽,只管發(fā)送,不管有沒有接收到
傳輸速度:TCP:慢徙垫。必須上一個傳完,下一個才能傳放棒。UDP:快间螟,它可以一直發(fā),不管你有沒有接收到
面向?qū)ο螅篢CP:面向連接1:1损肛。UDP:無連接,1:N治拿。一個很老得比喻,也很形象劫谅。你把TCP理解成個人視頻嚷掠,把UDP理解成群視頻。
開銷:TCP:開銷大不皆,首部20個字節(jié)。UDP開銷信Α:首部8個字節(jié)
4. 三次握手
??我們都知道TCP是全雙工可靠信道。什么是信道犬耻?感覺打字不如貼圖,如圖:
??然后枕磁,我們來看看這個TCP的通信圖
已知:兩個對象A和B坦胶,兩個信道:信道1和信道2。
第一次握手:A從信道1中給B發(fā)消息:我要跟你連接了顿苇。(說明:A可以從信道1發(fā)消息)
第二次握手:B從信道2中給A回消息:好的,我同意了纪岁。(說明:B可以從信道2發(fā)消息,B可以從信道1收消息)
第三次握手:A從信道1中給B回消息:那我們開始連接吧(A可以從信道2收消息)幔翰。B收到之后就建立了連接漩氨。
為什么必須要三次握手叫惊,2次不行嗎做修?
??全雙工信道只能單方向發(fā)消息饰及。如果是2次握手:表示A可以從信道1發(fā)消息燎含。B可以從信道1收消息宾濒,信道2發(fā)消息屏箍。但是橘忱,B并不知道A能不能從信道2收到消息鹦付。所以择卦,2次沒法建立建立秉继。
5. 四次揮手
第一次揮手:A從信道1給B發(fā)消息:我的事情都處理完了,我要跟你斷開連接了尚辑。
第二次揮手:B從信道1收到消息后,從信道2給A回一個消息:我知道了杠茬。然后,B繼續(xù)處理未處理完的事情宁赤。
第三次揮手:B的事情處理完之后决左,B從信道2給A發(fā)消息:我的事情都處理完了,我要跟你斷開連接了佛猛。
第四次揮手:A從信道2收到B發(fā)來的斷開連接的消息之后。A從信道1給B回復(fù):好的逃沿,我知道了,我們都斷開吧。然后触幼,A斷開1究飞,2信道。B從信道1收到了A的確認(rèn)消息之后瘟栖。B也斷開1半哟,2信道签餐。
5. 通信流程
- 先獲取Socket套接字對象,綁定端口號戒良,新開線程連接服務(wù)器糯崎。
- 然后通過套接字獲取它的輸入流和輸入流河泳。
- 新開兩個線程乔询,監(jiān)聽outputstream樟插,和inputstream黄锤。輸入流負(fù)責(zé)讀從服務(wù)器返回的數(shù)據(jù)鸵熟,輸出流負(fù)責(zé)本地向服務(wù)器發(fā)送數(shù)據(jù)负甸。
- 這個時候就需要注意拆包呻待,粘包的問題,返回數(shù)據(jù)需要統(tǒng)一格式奏篙,讀數(shù)據(jù)的時候可以根據(jù)這個格式來區(qū)分是否是一條完整的數(shù)據(jù)。
- 再就是需要監(jiān)聽網(wǎng)絡(luò)狀態(tài)的變化,若切換網(wǎng)絡(luò)導(dǎo)致連接中斷肺稀,這個時候就需要捕獲異常话原,釋放資源稿静,再重新連接控漠。
??一般如果沒有限制必須要用原生的寫悬钳,我一般都是用Netty默勾,之前也寫過一篇Netty用法的文章:Netty的簡單使用母剥,實現(xiàn)socket通訊
??解決粘包习霹,拆包:約定好每一條消息的規(guī)則炫隶。怎么約定呢?
舉個栗子:
- 定長伪阶。每條消息都是固定長度,不夠補(bǔ)0斟湃。每次只讀取一個固定長度的信息檐薯,這樣自然就把每條消息分開了。
- 設(shè)置特定的結(jié)束符祷膳。雙方約定好,每條消息的結(jié)尾跟一個特殊的符號搀军,表示這條消息結(jié)束罩句。這樣也能把每條消息分開
- 每條消息的頭部门烂,定義好這條消息的長度屯远。每次解析的時候,先解析這個長度,再開始解析數(shù)據(jù)泄私。