網(wǎng)絡(luò)編程基礎(chǔ)原理

1. 網(wǎng)絡(luò)編程概念

首先注意呈驶, Socket不是Java中獨(dú)有的概念捂掰,而是一個(gè)語(yǔ)言無(wú)關(guān)標(biāo)準(zhǔn)羡鸥。 任何可以實(shí)現(xiàn)網(wǎng)絡(luò)編程的編程語(yǔ)言都有 Socket 。

1.1 什么是 Socket

??網(wǎng)絡(luò)上的兩個(gè)程序通過(guò)一個(gè)雙向的通信連接實(shí)現(xiàn)數(shù)據(jù)的交換鉴腻,這個(gè)連接的一端稱為一個(gè) socket迷扇。
??建立網(wǎng)絡(luò)通信連接至少要一個(gè)端口號(hào)百揭。socket 本質(zhì)是編程接口(API),對(duì) TCP/IP 的封裝蜓席, TCP/IP 也要提供可供程序員做網(wǎng)絡(luò)開(kāi)發(fā)所用的接口信峻,這就是 Socket 編程接口;HTTP 是轎車瓮床, 提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket 是發(fā)動(dòng)機(jī)产镐,提供了網(wǎng)絡(luò)通信的能力隘庄。
?? Socket 的英文原義是“孔”或“插座”。作為 BSD UNIX 的進(jìn)程通信機(jī)制癣亚,取后一種意思丑掺。通常也稱作"套接字",用于描述 IP 地址和端口述雾,是一個(gè)通信鏈的句柄街州,可以用來(lái)實(shí)現(xiàn)不同虛 擬機(jī)或不同計(jì)算機(jī)之間的通信。在 Internet 上的主機(jī)一般運(yùn)行了多個(gè)服務(wù)軟件玻孟,同時(shí)提供幾 種服務(wù)唆缴。每種服務(wù)都打開(kāi)一個(gè) Socket,并綁定到一個(gè)端口上黍翎,不同的端口對(duì)應(yīng)于不同的服務(wù)面徽。 Socket 正如其英文原義那樣,像一個(gè)多孔插座匣掸。一臺(tái)主機(jī)猶如布滿各種插座的房間趟紊,每個(gè)插 座有一個(gè)編號(hào),有的插座提供 220 伏交流電碰酝, 有的提供 110 伏交流電霎匈,有的則提供有線電 視節(jié)目。 客戶軟件將插頭插到不同編號(hào)的插座送爸,就可以得到不同的服務(wù)铛嘱。

1.2 Socket 連接步驟

??根據(jù)連接啟動(dòng)的方式以及本地套接字要連接的目標(biāo),套接字之間的連接過(guò)程可以分為三 個(gè)步驟:服務(wù)器監(jiān)聽(tīng)碱璃,客戶端請(qǐng)求弄痹,連接確認(rèn)∏镀鳎【如果包含數(shù)據(jù)交互+斷開(kāi)連接肛真,那么一共是 五個(gè)步驟】

  1. 服務(wù)器監(jiān)聽(tīng):是服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連 接的狀態(tài)爽航,實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài)蚓让。
  2. 客戶端請(qǐng)求:是指由客戶端的套接字提出連接請(qǐng)求乾忱,要連接的目標(biāo)是服務(wù)器端的 套接字。為此历极,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字窄瘟,指出服務(wù)器端套 接字的地址和端口號(hào),然后就向服務(wù)器端套接字提出連接請(qǐng)求趟卸。
  3. 連接確認(rèn):是指當(dāng)服務(wù)器端套接字監(jiān)聽(tīng)到或者說(shuō)接收到客戶端套接字的連接請(qǐng)求蹄葱, 它就響應(yīng)客戶端套接字的請(qǐng)求,建立一個(gè)新的線程锄列,把服務(wù)器端套接字的描述發(fā)給客戶端图云, 一旦客戶端確認(rèn)了此描述,連接就建立好了邻邮。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽(tīng)狀態(tài)竣况,繼續(xù)接 收其他客戶端套接字的連接請(qǐng)求。
    image.png

    具體參考TCP三次握手,與四次揮手
1.3 Java 中的 Socket

??在 java.net 包是網(wǎng)絡(luò)編程的基礎(chǔ)類庫(kù)筒严。其中 ServerSocket 和 Socket 是網(wǎng)絡(luò)編程的基礎(chǔ)類 型丹泉。ServerSocket 是服務(wù)端應(yīng)用類型。Socket 是建立連接的類型鸭蛙。當(dāng)連接建立成功后摹恨,服務(wù)器和客戶端都會(huì)有一個(gè) Socket 對(duì)象示例,可以通過(guò)這個(gè) Socket 對(duì)象示例娶视,完成會(huì)話的所有 操作睬塌。
??對(duì)于一個(gè)完整的網(wǎng)絡(luò)連接來(lái)說(shuō),Socket 是平等的歇万,沒(méi)有服務(wù)器客戶端分級(jí)情況揩晴。

2. 什么是同步和異步

??同步和異步是針對(duì)應(yīng)用程序內(nèi)核的交互而言的,同步指的是用戶進(jìn)程觸發(fā) IO 操作并 等待或者輪詢的去查看 IO 操作是否就緒贪磺,而異步是指用戶進(jìn)程觸發(fā) IO 操作以后便開(kāi)始做自 己的事情硫兰,而當(dāng) IO 操作已經(jīng)完成的時(shí)候會(huì)得到 IO 完成的通知。
??以銀行取款為例:
??同步: 自己親自出馬持銀行卡到銀行取錢(使用同步 IO 時(shí)寒锚,Java 自己處理 IO 讀寫)劫映;
??異步 : 委托一小弟拿銀行卡到銀行取錢,然后給你(使用異步 IO 時(shí)刹前,Java 將 IO 讀寫 委托給 OS 處理泳赋,需要將數(shù)據(jù)緩沖區(qū)地址和大小傳給 OS(銀行卡和密碼),OS 需要支持異步 IO 操作 API)喇喉;

3. 什么是阻塞和非阻塞

??阻塞和非阻塞是針對(duì)于進(jìn)程在訪問(wèn)數(shù)據(jù)的時(shí)候祖今,根據(jù) IO 操作的就緒狀態(tài)來(lái)采取的不同 方式,說(shuō)白了是一種讀取或者寫入操作方法的實(shí)現(xiàn)方式,阻塞方式下讀取或者寫入函數(shù)將一 直等待千诬,而非阻塞方式下耍目,讀取或者寫入方法會(huì)立即返回一個(gè)狀態(tài)值。
??以銀行取款為例:
??阻塞 : ATM 排隊(duì)取款徐绑,你只能等待(使用阻塞 IO 時(shí)邪驮,Java 調(diào)用會(huì)一直阻塞到讀寫完 成才返回);
??非阻塞 : 柜臺(tái)取款傲茄,取個(gè)號(hào)毅访,然后坐在椅子上做其它事,等號(hào)廣播會(huì)通知你辦理盘榨,沒(méi) 到號(hào)你就不能去俺抽,你可以不斷問(wèn)大堂經(jīng)理排到了沒(méi)有,大堂經(jīng)理如果說(shuō)還沒(méi)到你就不能去(使 用非阻塞 IO 時(shí)较曼,如果不能讀寫 Java 調(diào)用會(huì)馬上返回,當(dāng) IO 事件分發(fā)器通知可讀寫時(shí)再繼 續(xù)進(jìn)行讀寫振愿,不斷循環(huán)直到讀寫完成)

4. BIO編程

??Blocking IO: 同步阻塞的編程方式捷犹。
??BIO 編程方式通常是在 JDK1.4 版本之前常用的編程方式。編程實(shí)現(xiàn)過(guò)程為:首先在服務(wù) 端啟動(dòng)一個(gè) ServerSocket 來(lái)監(jiān)聽(tīng)網(wǎng)絡(luò)請(qǐng)求冕末,客戶端啟動(dòng) Socket 發(fā)起網(wǎng)絡(luò)請(qǐng)求萍歉,默認(rèn)情況下 ServerSocket 回建立一個(gè)線程來(lái)處理此請(qǐng)求,如果服務(wù)端沒(méi)有線程可用档桃,客戶端則會(huì)阻塞等 待或遭到拒絕枪孩。
??且建立好的連接,在通訊過(guò)程中藻肄,是同步的蔑舞。在并發(fā)處理效率上比較低。大致結(jié)構(gòu)如下:


image.png

??同步并阻塞嘹屯,服務(wù)器實(shí)現(xiàn)模式為一個(gè)連接一個(gè)線程攻询,即客戶端有連接請(qǐng)求時(shí)服務(wù)器端就 需要啟動(dòng)一個(gè)線程進(jìn)行處理,如果這個(gè)連接不做任何事情會(huì)造成不必要的線程開(kāi)銷州弟,當(dāng)然可 以通過(guò)線程池機(jī)制改善钧栖。
??BIO 方式適用于連接數(shù)目比較小且固定的架構(gòu),這種方式對(duì)服務(wù)器資源要求比較高婆翔,并發(fā)局限于應(yīng)用中拯杠,JDK1.4 以前的唯一選擇,但程序直觀簡(jiǎn)單易理解啃奴。
??使用線程池機(jī)制改善后的 BIO 模型圖如下:


image.png

5. NIO 編程

??Unblocking IO(New IO): 同步非阻塞的編程方式潭陪。
??NIO 本身是基于事件驅(qū)動(dòng)思想來(lái)完成的,其主要想解決的是 BIO 的大并發(fā)問(wèn)題,NIO 基 于 Reactor畔咧,當(dāng) socket 有流可讀或可寫入 socket 時(shí)茎芭,操作系統(tǒng)會(huì)相應(yīng)的通知引用程序進(jìn)行處理,應(yīng)用再將流讀取到緩沖區(qū)或?qū)懭氩僮飨到y(tǒng)誓沸。也就是說(shuō)梅桩,這個(gè)時(shí)候,已經(jīng)不是一個(gè)連接就 要對(duì)應(yīng)一個(gè)處理線程了拜隧,而是有效的請(qǐng)求宿百,對(duì)應(yīng)一個(gè)線程,當(dāng)連接沒(méi)有數(shù)據(jù)時(shí)洪添,是沒(méi)有工作線程來(lái)處理的垦页。
??NIO 的最重要的地方是當(dāng)一個(gè)連接創(chuàng)建后,不需要對(duì)應(yīng)一個(gè)線程干奢,這個(gè)連接會(huì)被注冊(cè)到 多路復(fù)用器上面痊焊,所以所有的連接只需要一個(gè)線程就可以搞定,當(dāng)這個(gè)線程中的多路復(fù)用器 進(jìn)行輪詢的時(shí)候忿峻,發(fā)現(xiàn)連接上有請(qǐng)求的話薄啥,才開(kāi)啟一個(gè)線程進(jìn)行處理,也就是一個(gè)請(qǐng)求一個(gè)線程模式逛尚。
??在 NIO 的處理方式中垄惧,當(dāng)一個(gè)請(qǐng)求來(lái)的話,開(kāi)啟線程進(jìn)行處理绰寞,可能會(huì)等待后端應(yīng)用的 資源(JDBC 連接等)到逊,其實(shí)這個(gè)線程就被阻塞了,當(dāng)并發(fā)上來(lái)的話滤钱,還是會(huì)有 BIO 一樣的問(wèn)題觉壶。


image.png

??同步非阻塞,服務(wù)器實(shí)現(xiàn)模式為一個(gè)請(qǐng)求一個(gè)通道件缸,即客戶端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè) 到多路復(fù)用器上掰曾,多路復(fù)用器輪詢到連接有 I/O 請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。
??NIO 方式適用于連接數(shù)目多且連接比較短(輕操作)的架構(gòu)停团,比如聊天服務(wù)器旷坦,并發(fā)局 限于應(yīng)用中,編程復(fù)雜佑稠,JDK1.4 開(kāi)始支持秒梅。

Buffer:ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer;
Channel:SocketChannel,ServerSocketChannel;
Selector:Selector,AbstractSelector;
SelectionKey:OP_READ,OP_WRITE,OP_CONNECT,OP_ACCEPT;

6. AIO 編程

??Asynchronous IO: 異步非阻塞的編程方式
??與 NIO 不同,當(dāng)進(jìn)行讀寫操作時(shí)舌胶,只須直接調(diào)用 API 的 read 或 write 方法即可捆蜀。這兩種方法均為異步的,對(duì)于讀操作而言,當(dāng)有流可讀取時(shí)辆它,操作系統(tǒng)會(huì)將可讀的流傳入 read 方法的緩沖區(qū)誊薄,并通知應(yīng)用程序;對(duì)于寫操作而言锰茉,當(dāng)操作系統(tǒng)將write方法傳遞的流寫入完 畢時(shí)呢蔫,操作系統(tǒng)主動(dòng)通知應(yīng)用程序。即可以理解為飒筑,read/write 方法都是異步的片吊,完成后會(huì) 主動(dòng)調(diào)用回調(diào)函數(shù)。在 JDK1.7 中协屡,這部分內(nèi)容被稱作 NIO.2俏脊,主要在 java.nio.channels 包下增加了下面四個(gè)異步通道:
??1.AsynchronousSocketChannel
??2.AsynchronousServerSocketChannel
??3.AsynchronousSocketChannel
??4.AsynchronousServerSocketChannel
??異步非阻塞,服務(wù)器實(shí)現(xiàn)模式為一個(gè)有效請(qǐng)求一個(gè)線程肤晓,客戶端的 I/O 請(qǐng)求都是由 OS 先完成了再通知服務(wù)器應(yīng)用去啟動(dòng)線程進(jìn)行處理爷贫。
??AIO 方式使用于連接數(shù)目多且連接比較長(zhǎng)(重操作)的架構(gòu),比如相冊(cè)服務(wù)器补憾,充分調(diào) 用 OS 參與并發(fā)操作漫萄,編程比較復(fù)雜,JDK7 開(kāi)始支持余蟹。


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市子刮,隨后出現(xiàn)的幾起案子威酒,更是在濱河造成了極大的恐慌,老刑警劉巖挺峡,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葵孤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡橱赠,警方通過(guò)查閱死者的電腦和手機(jī)尤仍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狭姨,“玉大人宰啦,你說(shuō)我怎么就攤上這事”模” “怎么了赡模?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)师抄。 經(jīng)常有香客問(wèn)我漓柑,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任辆布,我火速辦了婚禮瞬矩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锋玲。我一直安慰自己景用,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布嫩絮。 她就那樣靜靜地躺著丛肢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剿干。 梳的紋絲不亂的頭發(fā)上蜂怎,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音置尔,去河邊找鬼杠步。 笑死,一個(gè)胖子當(dāng)著我的面吹牛榜轿,可吹牛的內(nèi)容都是我干的幽歼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼谬盐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼甸私!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起飞傀,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤皇型,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后砸烦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體弃鸦,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年幢痘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唬格。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颜说,死狀恐怖购岗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情门粪,我是刑警寧澤藕畔,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站庄拇,受9級(jí)特大地震影響注服,放射性物質(zhì)發(fā)生泄漏韭邓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一溶弟、第九天 我趴在偏房一處隱蔽的房頂上張望女淑。 院中可真熱鬧,春花似錦辜御、人聲如沸鸭你。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)袱巨。三九已至,卻和暖如春碳抄,著一層夾襖步出監(jiān)牢的瞬間愉老,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工剖效, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嫉入,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓璧尸,卻偏偏與公主長(zhǎng)得像咒林,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爷光,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355