日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

从tcp到netty(一)

發(fā)布時(shí)間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从tcp到netty(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  發(fā)現(xiàn)自己近一年有些毛病,自己也算是研習(xí)了不少的源代碼,看了不少的技術(shù)書籍,但是自己就是記憶力不行,總是過(guò)段時(shí)間就會(huì)忘記,忘記之后還得從頭開始啃源碼、啃書籍。而且有些重要技術(shù)點(diǎn)也會(huì)遺忘,導(dǎo)致再學(xué)習(xí)的時(shí)候發(fā)現(xiàn)自己又回到了起點(diǎn)!我總結(jié)為,就是自己近一年期間犯懶,沒有再寫一下博客,技能點(diǎn)不能很好的再回顧!

  趁著發(fā)現(xiàn)自己的問(wèn)題,同時(shí)自己也在做前后端rpc分離實(shí)踐,現(xiàn)在將之前研習(xí)netty的結(jié)果再總結(jié)出來(lái),寫到博客上!

  首先,我們要確定java中的netty用來(lái)做什么的?具體的工作模式優(yōu)勢(shì)不解釋,網(wǎng)上能找一大堆,主要講它通信這塊的rpc,高效穩(wěn)定的協(xié)議棧繞不開tcp/ip協(xié)議!

  本來(lái)是不想記錄tcp/ip的,這個(gè)實(shí)在是沒有太多好說(shuō)的,但是也發(fā)現(xiàn)雖然自己明白,有時(shí)候卻也是會(huì)遺漏要點(diǎn)知識(shí),所以也還是記錄一下吧!

  似乎作為上層程序員只需要了解tcp的握手與揮手情況即可!

  首先要了解tcp/ip的頭部結(jié)構(gòu)

16位源端端口 ??| ?16位目標(biāo)端端口

32位序列號(hào)(發(fā)送端確認(rèn)信息)

32位確認(rèn)序號(hào)(服務(wù)端確認(rèn))

4位偏移量(每個(gè)數(shù)字表示1個(gè)4字節(jié),所以最大表示15個(gè)4字節(jié),也就是60字節(jié))----

6位保留位(記不太清了) ?| 標(biāo)志位:包括6種報(bào)文段 urg、ack、rst、syn、fin、psh

16位校驗(yàn)和 ????| ????16位緊急指針

16位窗口大小(用于tcp緩沖區(qū)的控制)

40位填充字段。

  我覺得挺容易理解的,作為通信雙方必須知道相互的地址,所以要有源地址與目標(biāo)地址的標(biāo)記;序列號(hào)與確認(rèn)序列號(hào),這個(gè)涉及到數(shù)據(jù)包分片,比如mtu導(dǎo)致了數(shù)據(jù)分片,如何分片與如何重組分片;偏移數(shù)據(jù)表示tcp頭部結(jié)構(gòu)能夠占用的最大數(shù)據(jù)長(zhǎng)度;保留位大概就是保留用的吧;標(biāo)記位,6個(gè)就是我們常說(shuō)的同步報(bào)文段、確認(rèn)報(bào)文段的標(biāo)記;窗口大小表示一次傳輸數(shù)據(jù)的大小,由于是16位,按照二進(jìn)制計(jì)算也就是65535字節(jié);校驗(yàn)和據(jù)說(shuō)是為了教研數(shù)據(jù)有效性的,我通過(guò)抓tcp的包看到類似這樣的16位緊急指針,這個(gè)是配和urg報(bào)文段設(shè)置優(yōu)先緊急數(shù)據(jù)的。

  然后是三次握手,與四次揮手中tcp狀態(tài)的轉(zhuǎn)移。都是基于上面tcp頭部結(jié)構(gòu)進(jìn)行變化的。

三次握手

1):client將syn標(biāo)志位置1,序列號(hào)seq置x(隨機(jī)數(shù)), 發(fā)送到server端,client狀態(tài)為同步發(fā)送狀態(tài),表示等待server端的確認(rèn);

2):server端收到client端數(shù)據(jù)包,判斷syn=1,了解到為同步報(bào)文段。則這時(shí),將要發(fā)送數(shù)據(jù)的tcp頭部分別設(shè)置syn與ack為1,確認(rèn)序列號(hào)x+1,序列號(hào)置y(隨機(jī)數(shù)),發(fā)送到

  client端,server端狀態(tài)為同步接收狀態(tài);

3):client端收到serve數(shù)據(jù)包之后,判斷是否ack報(bào)文段為1,確認(rèn)序列號(hào)是否為x+1,符合則將要發(fā)送的數(shù)據(jù)的tcp頭部的ack報(bào)文段置1,確認(rèn)序列號(hào)y+1,然后發(fā)送;到達(dá)server端

  之后,檢查ack報(bào)文段是否為1 && 確認(rèn)序列號(hào)是否為y+1,符合則建立連接。

  此時(shí)client與server都進(jìn)入了建立成功階段。

四次揮手

1): client將要發(fā)送報(bào)文信息的tcp頭部的fin報(bào)文段置1,序列號(hào)置隨機(jī)值x,發(fā)送給server端,client端狀態(tài)為結(jié)束等待狀態(tài);

2): server端收到fin結(jié)束報(bào)文段,將發(fā)送報(bào)文信息的tcp頭部ack置1,確認(rèn)序號(hào)為x+1,server端進(jìn)入關(guān)閉等待階段;

3):server端再次發(fā)送一個(gè)報(bào)文數(shù)據(jù),tcp頭部fin置1,此時(shí)server端進(jìn)入了最后確認(rèn)階段;

4):client接收到了server的ack報(bào)文信息與fin報(bào)文信息之后,驗(yàn)證確認(rèn)序列號(hào)x+1,然后再向server端發(fā)送一個(gè)tcp頭部ack=1的報(bào)文段,client進(jìn)入time_wait階段,server端收到信息

  驗(yàn)證后進(jìn)入關(guān)閉狀態(tài);

最后的時(shí)刻client等待2*msl(最大報(bào)文傳輸時(shí)間)時(shí)間長(zhǎng)度,進(jìn)入close狀態(tài)。

  第二繞不開的一點(diǎn)就是網(wǎng)絡(luò)的io模型!一般我們應(yīng)該都知道有幾種常談的io模型,阻塞式、非阻塞、異步io、多路復(fù)用、信號(hào)驅(qū)動(dòng)的io模型,這里java常用的就是非阻塞式io與多路復(fù)用io也就是nio!nio基reactor的模型進(jìn)行設(shè)計(jì)的。所以接下來(lái)要講一下nio與reactor模型。

  Nio,這個(gè)我們需要去看epoll的解釋,最好去看epoll的源碼,這里我建議看一下深入理解nginx這本書中的epoll的解釋,詳細(xì)描述了代碼狀況!下面具體談一下epoll的優(yōu)秀思想設(shè)計(jì)。

  首先要知道原來(lái)模式的弊端,原有linux2.6之前的操作系統(tǒng),采用select/poll的形式這兩種形式在進(jìn)行連接事件的收集的時(shí)候,是將所有活躍與不活躍的套接字由用戶態(tài)的內(nèi)存向操作系統(tǒng)的內(nèi)核內(nèi)存?zhèn)鬟f,然后由操作系統(tǒng)內(nèi)核掃描所有套接字,不管是內(nèi)存還是cpu都造成巨大的浪費(fèi)。而epoll則不是,它定義了一個(gè)文件系統(tǒng),首先,調(diào)用epoll_create創(chuàng)建一個(gè)epoll對(duì)象;然后,調(diào)用epoll_ctl向epoll添加所有的連接套接字;第三,調(diào)用epoll_wait收集活躍的連接這樣它就避免了完全的內(nèi)存復(fù)制,只進(jìn)行收集活躍連接,然后也不用遍歷原來(lái)所有的連接,使cpu也降溫。

  Eventpoll是創(chuàng)建epoll時(shí)候的數(shù)據(jù)結(jié)構(gòu),里面是一種紅黑樹的數(shù)據(jù)結(jié)構(gòu),用于存儲(chǔ)epoll_ctl向epoll對(duì)象中添加的事件,為什么使用紅黑樹,因?yàn)槿绻霈F(xiàn)重復(fù)的套接字可以很快的識(shí)別出來(lái)。據(jù)書上說(shuō),被添加到epoll中的時(shí)間都會(huì)與網(wǎng)卡建立回調(diào)關(guān)系epoll_callback。Eventpoll中含有一個(gè)紅黑樹的根節(jié)點(diǎn)rbr與雙向鏈表rdllist,回調(diào)事件會(huì)放到rdllist,所以epoll_wait掃描事件連接的時(shí)候就只針對(duì)這個(gè)rdllist的鏈表進(jìn)行遍歷,然后將事件復(fù)制給用戶內(nèi)存,所以也就保證了效率。

  第三,Reactor模式(也有人叫做反應(yīng)器模式)!Netty中的nio線程模型命名了三種模式:Reactor單線程模型、Reactor多線程模型和主從多線程模型!實(shí)際上都是根據(jù)上邊epoll的三階段進(jìn)行的劃分,所以抽象出這三種階段才能更好的理解這三種設(shè)計(jì)的模型,也就是得理解epoll的三種事件!所有這三種模型都是圍繞著三種階段進(jìn)行的。

  單線程模型:就是說(shuō)把這三個(gè)階段統(tǒng)統(tǒng)放在一個(gè)線程上操作。該線程負(fù)責(zé),創(chuàng)建事件對(duì)象,accept收集活躍socket,分發(fā)器分發(fā)二進(jìn)制消息進(jìn)行讀寫操作(接收數(shù)據(jù)、發(fā)送數(shù)據(jù))。

  多線程模型:這個(gè)其實(shí)主要是將收集活躍的socket與事件分發(fā)分成了兩步;一個(gè)專門的線程用于收集活躍的socket,另一個(gè)線程池專門負(fù)責(zé)數(shù)據(jù)的讀寫操作;

  主從多線程模型:這個(gè)其實(shí)是在多線程模型上進(jìn)一步的加固;用來(lái)收集活躍socket的線程改成了線程池,acceptor接收到tcp socket接收驗(yàn)證(這個(gè)應(yīng)該是指的tcp的數(shù)據(jù)驗(yàn)證)連接后,將該連接的通道交給io處理線程池的一個(gè)線程上進(jìn)行io的讀寫操作。

  實(shí)際上就是這么回事,只是將原來(lái)串行的操作改成了并行化,同時(shí)保證線程的安全性!

轉(zhuǎn)載于:https://www.cnblogs.com/kevinfuture/p/8494648.html

總結(jié)

以上是生活随笔為你收集整理的从tcp到netty(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。