萬丈高樓平地起---TCP鏈接

《計算機網(wǎng)絡(luò)》給我們仔仔細細的講了TCP/IP協(xié)議的5層架構(gòu),在理論層面分析了數(shù)據(jù)如何從上而下,變成了二進制信號阿宅,最后通過電纜傳輸?shù)椒?wù)端。而服務(wù)端又從下而上笼蛛,將電信號解析洒放,最后層層封裝成我們需要的數(shù)據(jù)。

而這一切和我們的Java有什么關(guān)系呢滨砍,且看下文往湿。

簡單說一下Socket

對于部分Android程序員來說妖异,直接用Java去和服務(wù)端通信可能是很久遠的事情了,現(xiàn)在來回顧一下代碼:

客戶端代碼

/** 
* Socket客戶端
*/
  public static void main(String[] args) {
       //創(chuàng)建Socket對象
      Socket socket=new Socket("localhost",8888);
      OutputStream outputStream=socket.getOutputStream();//獲取一個輸出流领追,向服務(wù)端發(fā)送信息          
      PrintWriter printWriter=new PrintWriter(outputStream);//將輸出流包裝成打印流
      printWriter.print("服務(wù)端你好!");
      printWriter.flush();
      socket.shutdownOutput();//關(guān)閉輸出流
  }

客戶端的整個過程非常簡單他膳,清晰

  1. 建立Socket連接(底層相當(dāng)于建立TCP連接)
  2. 獲取Socket連接的輸出流(如果鏈接建立失敗,則會拋出異常)
  3. 向流中寫入數(shù)據(jù)蔓腐,并flush(這代表數(shù)據(jù)發(fā)送到服務(wù)端)
  4. 關(guān)閉輸入流(流對象在操作系統(tǒng)看來是一種資源矩乐,上層使用完之后必須關(guān)閉)

那么,Socket到底是個什么東西呢回论?

每一種編程語言都要進行網(wǎng)絡(luò)操作散罕,而TCP/IP協(xié)議是計算機體系層面的,他是一個通用的概念傀蓉,所以Java就對其封裝成了一個Socket類欧漱,對于Java開發(fā)者來說,要想進行網(wǎng)絡(luò)通信葬燎,使用Socket對象就可以了误甚。

TCP連接

計算機體系是一個嚴謹?shù)膶蛹壗Y(jié)構(gòu),下層為上層提供接口谱净,上層只需要按照下層提供的接口傳輸數(shù)據(jù)窑邦,就可以和下層通信。比如操作系統(tǒng)壕探,它本身也是一個運行在計算機中的軟件冈钦,他為應(yīng)用程序提供接口,應(yīng)用程序就可以間接調(diào)用操作系統(tǒng)的資源李请。
TCP的全稱是傳輸層控制協(xié)議瞧筛,它的作用是和服務(wù)器之間建立起通信的管道,后續(xù)的所有數(shù)據(jù)都要通過這個管道傳輸?shù)椒?wù)器上导盅,當(dāng)數(shù)據(jù)傳輸完成以后较幌,這個管道(在操作系統(tǒng)看來是一種資源)會被關(guān)閉。
建立管道的過程就是TCP的3次握手

  1. 客戶端發(fā)送SYN報文給服務(wù)器端白翻,客戶端進入SYN_SEND狀態(tài)乍炉。
  2. 服務(wù)端收到SYN報文,回應(yīng)一個SYN ACK報文滤馍,服務(wù)端進入SYN_RECV狀態(tài)
  3. 客戶端收到服務(wù)端的SYN報文恩急,回應(yīng)一個ACK報文,客戶端進入ESTABLISHED狀態(tài)纪蜒;服務(wù)端收到這個ACK報文后,進入ESTABLISHED狀態(tài)此叠。

那么纯续,問題來了随珠,為什么要進行3次握手呢?

明明2次就可以建立連接的猬错,計算機網(wǎng)絡(luò)中的解釋如下:

為了防止已失效的請求報文突然又傳送到了服務(wù)端窗看,因而產(chǎn)生錯誤。

舉個栗子:

什么叫"已失效的請求報文"呢倦炒?
client第一次發(fā)出的請求報文在某個網(wǎng)絡(luò)節(jié)點滯留显沈,以致于該報文到達Server后,TCP連接已經(jīng)被客戶端釋放逢唤。此時拉讯,如果不采用"三次握手",那么服務(wù)端會認為客戶端想和它建立連接鳖藕,就會一直傻傻的等著魔慷,這樣白白浪費了server的資源。
如果采用了"三次握手"著恩,server收到滯留報文后給client發(fā)出確認消息院尔,client不會向server作出回應(yīng),server由于收不到確認喉誊,也就不會建立連接邀摆。

終止連接需要4次揮手

細節(jié)略。


tcp三次握手.png

KeepAlive和心跳包

首先明確一點伍茄,在TCP層是沒有“請求”一說的栋盹,TCP是一種通信方式(對應(yīng)的還有UDP)』昧郑”請求“一詞是事務(wù)上的概念贞盯,HTTP協(xié)議是一種事務(wù)協(xié)議,所以我們可以說發(fā)送一個HTTP請求沪饺。

TCP層的KeepAlive

當(dāng)TCP連接建立后躏敢,如果上層協(xié)議一直不發(fā)送數(shù)據(jù),或者隔了很長時間才發(fā)送一次數(shù)據(jù)整葡,TCP層需要自己去解決這個問題件余。
當(dāng)超過一段時間后,TCP自動發(fā)送一個數(shù)據(jù)為空的報文給對方遭居,如果對方回應(yīng)了啼器,說明對方還在線,連接可以繼續(xù)保持俱萍;如果對方?jīng)]有報文返回端壳,并且在重試了多次之后則認為連接丟失。
注意:上述的實現(xiàn)在TCP層完成枪蘑。

HTTP層的Keep-Alive

一個完整的HTTP事物如下:

  1. 建立連接
  2. 傳輸數(shù)據(jù)
  3. 關(guān)閉連接

在展示一個網(wǎng)頁時损谦,可能有很多次請求岖免,圖片,JS,CSS等等,如果每一個HTTP請求都需要一個完整的HTTP事務(wù)來完成照捡,這樣的開銷(建立連接颅湘、關(guān)閉連接)是沒必要的。
開啟了HTTP Keep-Alive之后栗精,能復(fù)用已有的TCP連接闯参。HTTP/1.1之后默認開啟Keep-Alive, 在HTTP的頭域中增加Connection選項。當(dāng)設(shè)置為Connection:keep-alive表示開啟悲立,設(shè)置為Connection:close表示關(guān)閉鹿寨。

App中的長連接

首先,這里的長連接肯定是TCP層面的連接级历。上面已經(jīng)提到過释移,TCP層建立的連接本身就是一個長連接,系統(tǒng)默認的探測時間是2小時寥殖。
對于移動端來說玩讳,他被分配的IP是內(nèi)網(wǎng)IP,它通過NAT發(fā)送數(shù)據(jù)到外網(wǎng)的服務(wù)器嚼贡,NAT內(nèi)部維護了一張映射表熏纯,這個表有一個維持時間,如果一段時間之后移動端沒有再發(fā)送數(shù)據(jù)粤策,那么移動端的IP在這張映射表上就會被抹掉樟澜。那么服務(wù)器也就不可能再推送消息給移動端了。
所以叮盘,移動端必須在一定的間隔時間內(nèi)去發(fā)送一個"心跳包"來維護NAT上的映射表秩贰,這樣NAT才能將服務(wù)端推送的消息轉(zhuǎn)發(fā)給移動端。
長連接具體的實現(xiàn)例子很多柔吼,根據(jù)不同的業(yè)務(wù)場景而不同毒费,但原理是一樣的。

參考文章:
一個運維對KeepAlive的理解

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愈魏,一起剝皮案震驚了整個濱河市觅玻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌培漏,老刑警劉巖溪厘,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異牌柄,居然都是意外死亡畸悬,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門珊佣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋宦,“玉大人闺骚,你說我怎么就攤上這事∽钡担” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵虫碉,是天一觀的道長贾惦。 經(jīng)常有香客問我,道長敦捧,這世上最難降的妖魔是什么须板? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮兢卵,結(jié)果婚禮上习瑰,老公的妹妹穿的比我還像新娘。我一直安慰自己秽荤,他們只是感情好甜奄,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著窃款,像睡著了一般课兄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晨继,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天烟阐,我揣著相機與錄音,去河邊找鬼紊扬。 笑死蜒茄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的餐屎。 我是一名探鬼主播檀葛,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啤挎!你這毒婦竟也來了驻谆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤庆聘,失蹤者是張志新(化名)和其女友劉穎胜臊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伙判,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡象对,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宴抚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勒魔。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡甫煞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冠绢,到底是詐尸還是另有隱情抚吠,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布弟胀,位于F島的核電站楷力,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏孵户。R本人自食惡果不足惜萧朝,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夏哭。 院中可真熱鬧检柬,春花似錦、人聲如沸竖配。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽械念。三九已至头朱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間龄减,已是汗流浹背项钮。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留希停,地道東北人烁巫。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像宠能,于是被迫代替她去往敵國和親亚隙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.這篇文章不是本人原創(chuàng)的违崇,只是個人為了對這部分知識做一個整理和系統(tǒng)的輸出而編輯成的阿弃,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,037評論 6 174
  • 當(dāng) app 和服務(wù)器進行通信的時候渣淳,大多數(shù)情況下,都是采用 HTTP 協(xié)議伴箩。HTTP 最初是為 web 瀏覽器而定...
    Flysss1219閱讀 1,254評論 0 4
  • 本文主要通過整理網(wǎng)絡(luò)上的資料入愧,整理出的關(guān)于TCP方面的簡單理論知識。作為Java程序員雖然更多的時候我們都是直接調(diào)...
    tomas家的小撥浪鼓閱讀 5,533評論 1 100
  • 1、TCP狀態(tài)linux查看tcp的狀態(tài)命令:1)棺蛛、netstat -nat 查看TCP各個狀態(tài)的數(shù)量2)怔蚌、lso...
    北辰青閱讀 9,398評論 0 11
  • 18.1 引言 TCP是一個面向連接的協(xié)議。無論哪一方向另一方發(fā)送數(shù)據(jù)之前旁赊,都必須先在雙方之間建立一條連接桦踊。本章將...
    張芳濤閱讀 3,344評論 0 13