青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

陳碩的Blog

關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗

陳碩 (giantchen AT gmail)

blog.csdn.net/Solstice

前幾天我在新浪微博上出了兩道有關(guān) TCP 的思考題,引發(fā)了一場討論 http://weibo.com/1701018393/eCuxDrta0Nn 。

第一道初級題目是:

有一臺機器,它有一個 IP,上面運行了一個 TCP 服務(wù)程序,程序只偵聽一個端口,問:從理論上講(只考慮 TCP/IP 這一層面,不考慮IPv6)這個服務(wù)程序可以支持多少并發(fā) TCP 連接?答 65536 上下的直接刷掉。

具體來說,這個問題等價于:有一個 TCP 服務(wù)程序的地址是 1.2.3.4:8765,問它從理論上能接受多少個并發(fā)連接?

第二道進階題目是:

一臺被測機器 A,功能同上,同一交換機上還接有一臺機器 B,如果允許 B 的程序直接收發(fā)以太網(wǎng) frame,問:讓 A 承擔(dān) 10 萬個并發(fā) TCP 連接需要用多少 B 的資源?100萬個呢?

從討論的結(jié)果看,很多人做出了第一道題,而第二道題幾乎無人問津。

 

這里先不公布答案(第一題答案見文末),讓我們繼續(xù)思考一個本質(zhì)的問題:一個 TCP 連接要占用多少系統(tǒng)資源。

在現(xiàn)在的 Linux 操作系統(tǒng)上,如果用 socket()/connect() 或 accept() 來創(chuàng)建 TCP 連接,那么每個連接至少要占用一個文件描述符(file descriptor)。為什么說“至少”?因為文件描述符可以復(fù)制,比如 dup();也可以被繼承,比如 fork();這樣可能出現(xiàn)系統(tǒng)里邊同一個 TCP 連接有多個文件描述符與之對應(yīng)。據(jù)此,很多人給出的第一題答案是:并發(fā)連接數(shù)受限于系統(tǒng)能同時打開的文件數(shù)目的最大值。這個答案在實踐中是正確的,卻不符合原題意。

 

如果拋開操作系統(tǒng)層面,只考慮 TCP/IP 層面,建立一個 TCP 連接有哪些開銷?理論上最小的開銷是多少?考慮兩個場景:

1. 假設(shè)有一個 TCP 服務(wù)程序,向這個程序成功發(fā)起連接需要做哪些事情?換句話說,如何才能讓這個 TCP 服務(wù)程序認(rèn)為有客戶連接到了它(讓它的 accept() 調(diào)用正常返回)?

2. 假設(shè)有一個 TCP 客戶端程序,讓這個程序成功建立到服務(wù)器的連接需要做哪些事情?換句話說,如何才能讓這個 TCP 客戶端程序認(rèn)為它自己已經(jīng)連接到服務(wù)器了(讓它的 connect() 調(diào)用正常返回)?

以上這兩個問題問的不是如何編程,如何調(diào)用 Sockets API,而是問如何讓操作系統(tǒng)的 TCP/IP 協(xié)議棧認(rèn)為任務(wù)已經(jīng)成功完成,連接已經(jīng)成功建立。

 

學(xué)過 TCP/IP 協(xié)議,理解三路握手的同學(xué)明白,TCP 連接是虛擬的連接,不是電路連接,維持 TCP 連接理論上不占用網(wǎng)絡(luò)資源(會占用兩頭程序的系統(tǒng)資源)。只要連接的雙方認(rèn)為 TCP 連接存在,并且可以互相發(fā)送 IP packet,那么 TCP 連接就一直存在。

對于問題 1,向一個 TCP 服務(wù)程序發(fā)起一個連接,客戶端(為明白起見,以下稱為 faketcp 客戶端)只需要做三件事情(三路握手):

1a. 向 TCP 服務(wù)程序發(fā)一個 IP packet,包含 SYN 的 TCP segment

1b. 等待對方返回一個包含 SYN 和 ACK 的 TCP segment

1c. 向?qū)Ψ桨l(fā)送一個包含 ACK 的 segment

在做完這三件事情之后,TCP 服務(wù)器程序會認(rèn)為連接已建立。而做這三件事情并不占用客戶端的資源(?),如果faketcp 客戶端程序可以繞開操作系統(tǒng)的 TCP/IP 協(xié)議棧,自己直接發(fā)送并接收 IP packet 或 Ethernet frame 的話。換句話說,faketcp 客戶端可以一直重復(fù)做這三件事件,每次用一個不同的 IP:PORT,在服務(wù)端創(chuàng)建不計其數(shù)的 TCP 連接,而 faketcp 客戶端自己毫發(fā)無損。很快我們將看到如何用程序來實現(xiàn)這一點。

對于問題 2,為了讓一個 TCP 客戶端程序認(rèn)為連接已建立,faketcp 服務(wù)端只需要做兩件事情:

2a. 等待客戶端發(fā)來的 SYN TCP segment

2b. 發(fā)送一個包含 SYN 和 ACK 的 TCP segment

2c. 忽視對方發(fā)來的包含 ACK 的 segment

在做完這兩件事情(收一個 SYN、發(fā)一個 SYN+ACK)之后,TCP 客戶端程序會認(rèn)為連接已建立。而做這三件事情并不占用 faketcp 服務(wù)端的資源(?)換句話說,faketcp 服務(wù)端可以一直重復(fù)做這兩件事件,接受不計其數(shù)的 TCP 連接,而 faketcp 服務(wù)端自己毫發(fā)無損。很快我們將看到如何用程序來實現(xiàn)這一點。

 

基于對以上兩個問題的分析,說明單獨談?wù)摗癟CP 并發(fā)連接數(shù)”是沒有意義的,因為連接數(shù)基本上是要多少有多少。更有意義的性能指標(biāo)或許是:“每秒鐘收發(fā)多少條消息”、“每秒鐘收發(fā)多少字節(jié)的數(shù)據(jù)”、“支持多少個活動的并發(fā)客戶”等等。

faketcp 的程序?qū)崿F(xiàn)

代碼見: https://github.com/chenshuo/recipes/tree/master/faketcp 可以直接用 make 編譯

為了驗證我上面的說法,我寫了幾個小程序來實現(xiàn) faketcp,這幾個程序可以發(fā)起或接受不計其數(shù)的 TCP 并發(fā)連接,并且不消耗操作系統(tǒng)資源,連動態(tài)內(nèi)存分配都不會用到。

我家里有一臺運行 Ubuntu Linux 10.04 的 PC 機,hostname 是 atom,所有的試驗都在這上面進行。

家里試驗環(huán)境的網(wǎng)絡(luò)配置是:

net

陳碩在《談一談網(wǎng)絡(luò)編程學(xué)習(xí)經(jīng)驗》中曾提到“可以用 TUN/TAP 設(shè)備在用戶態(tài)實現(xiàn)一個能與本機點對點通信的 TCP/IP 協(xié)議?!?,這次的試驗正好可以用上這個辦法。

試驗的網(wǎng)絡(luò)配置是:

tun

具體做法是:在 atom 上通過打開 /dev/net/tun 設(shè)備來創(chuàng)建一個 tun0 虛擬網(wǎng)卡,然后把這個網(wǎng)卡的地址設(shè)為 192.168.0.1/24,這樣 faketcp 程序就扮演了 192.168.0.0/24 這個網(wǎng)段上的所有機器。atom 發(fā)給 192.168.0.2~192.168.0.254 的 IP packet 都會發(fā)給 faketcp 程序,faketcp 程序可以模擬其中任何一個 IP 給 atom 發(fā) IP packet。

程序分成幾步來實現(xiàn)。

第一步:實現(xiàn) icmp echo 協(xié)議,這樣就能 ping 通 faketcp 了。

代碼見 https://github.com/chenshuo/recipes/blob/master/faketcp/icmpecho.cc

其中響應(yīng) icmp echo request 的函數(shù)在 https://github.com/chenshuo/recipes/blob/master/faketcp/faketcp.cc#L57 這個函數(shù)在后面的程序中也會用到。

運行方法,打開 3 個命令行窗口:

1. 在第 1 個窗口運行 sudo ./icmpecho ,程序顯示

allocted tunnel interface tun0

2. 在第 2 個窗口運行

$ sudo ifconfig tun0 192.168.0.1/24

$ sudo tcpdump -i tun0

3. 在第 3 個窗口運行

$ ping 192.168.0.2

$ ping 192.168.0.3

$ ping 192.168.0.234

發(fā)現(xiàn)每個 192.168.0.X 的 IP 都能 ping 通。

 

第二步:實現(xiàn)拒絕 TCP 連接的功能,即在收到 SYN TCP segment 的時候發(fā)送 RST segment。

代碼見 https://github.com/chenshuo/recipes/blob/master/faketcp/rejectall.cc

運行方法,打開 3 個命令行窗口,頭兩個窗口的操作與前面相同,運行的 faketcp 程序是 ./rejectall

3. 在第 3 個窗口運行

$ nc 192.168.0.2 2000

$ nc 192.168.0.2 3333

$ nc 192.168.0.7 5555

發(fā)現(xiàn)向其中任意一個 IP 發(fā)起的 TCP 連接都被拒接了。

 

第三步:實現(xiàn)接受 TCP 連接的功能,即在收到SYN TCP segment 的時候發(fā)回 SYN+ACK。這個程序同時處理了連接斷開的情況,即在收到 FIN segment 的時候發(fā)回 FIN+ACK。

代碼見 https://github.com/chenshuo/recipes/blob/master/faketcp/acceptall.cc

運行方法,打開 3 個命令行窗口,步驟與前面相同,運行的 faketcp 程序是 ./acceptall。這次會發(fā)現(xiàn) nc 能和 192.168.0.X 中的每一個 IP 每一個 PORT 都能連通。還可以在第 4 個窗口中運行 netstat –tpn ,以確認(rèn)連接確實建立起來了。如果在 nc 中輸入數(shù)據(jù),數(shù)據(jù)會堆積在操作系統(tǒng)中,表現(xiàn)為 netstat 顯示的發(fā)送隊列(Send-Q)的長度增加。

 

第四步:在第三步接受 TCP 連接的基礎(chǔ)上,實現(xiàn)接收數(shù)據(jù),即在收到包含 payload 數(shù)據(jù) 的 TCP segment 時發(fā)回 ACK。

代碼見 https://github.com/chenshuo/recipes/blob/master/faketcp/discardall.cc

運行方法,打開 3 個命令行窗口,步驟與前面相同,運行的 faketcp 程序是 ./acceptall。這次會發(fā)現(xiàn) nc 能和 192.168.0.X 中的每一個 IP 每一個 PORT 都能連通,數(shù)據(jù)也能發(fā)出去。還可以在第 4 個窗口中運行 netstat –tpn ,以確認(rèn)連接確實建立起來了,并且發(fā)送隊列的長度為 0。

這一步已經(jīng)解決了前面的問題 2,扮演任意 TCP 服務(wù)端。

 

第五步:解決前面的問題 1,扮演客戶端向 atom 發(fā)起任意多的連接。

代碼見 https://github.com/chenshuo/recipes/blob/master/faketcp/connectmany.cc

這一步的運行方法與前面不同,打開 4 個命令行窗口。

1. 在第 1 個窗口運行 sudo ./connectmany 192.168.0.1 2007 1000 ,表示將向 192.168.0.1:2007 發(fā)起 1000 個并發(fā)連接。

程序顯示

allocted tunnel interface tun0
press enter key to start connecting 192.168.0.1:2007

 

2. 在第 2 個窗口運行

$ sudo ifconfig tun0 192.168.0.1/24

$ sudo tcpdump -i tun0

3. 在第 3 個窗口運行一個能接收并發(fā) TCP 連接的服務(wù)程序,可以是 httpd,也可以是 muduo 的 echo 或 discard 示例,程序應(yīng) listen 2007 端口。

4. 回到第 1 個窗口中敲回車,然后在第 4 個窗口中用 netstat -tpn 來觀察并發(fā)連接。

 

有興趣的話,還可以繼續(xù)擴展,做更多的有關(guān) TCP 的試驗,以進一步加深理解,驗證操作系統(tǒng) TCP/IP 協(xié)議棧面對不同輸入的行為。甚至可以按我在《談一談網(wǎng)絡(luò)編程學(xué)習(xí)經(jīng)驗》中提議的那樣,實現(xiàn)完整的 TCP 狀態(tài)機,做出一個簡單的 mini tcp stack。

 

第一道題的答案:

在只考慮 IPv4 的情況下,并發(fā)數(shù)的理論上限是 2**48??紤]某些 IP 段被保留了,這個上界可適當(dāng)縮小,但數(shù)量級不變。實際的限制是操作系統(tǒng)全局文件描述符的數(shù)量,以及內(nèi)存大小。

一個 TCP 連接有兩個 end points,每個 end point 是 {ip, port},題目說其中一個 end point 已經(jīng)固定,那么留下一個 end point 的自由度,即 2 ** 48??蛻舳?IP 的上限是 2**32 個,每個客戶端IP發(fā)起連接的上限是 2**16,乘到一起得理論上限。

即便客戶端使用 NAT,也不影響這個理論上限。(為什么?)

 

在真實的 Linux 系統(tǒng)中,可以通過調(diào)整內(nèi)核參數(shù)來支持上百萬并發(fā)連接,具體做法見:

http://urbanairship.com/blog/2010/09/29/linux-kernel-tuning-for-c500k/

http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-3

 

(.完.)

posted on 2011-07-01 12:50 陳碩 閱讀(6759) 評論(7)  編輯 收藏 引用 所屬分類: muduo

評論

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗 2011-07-01 22:38 lijsf

你好,我有個問題想問一下,像這樣的并發(fā)連接,在UDP上是否可以實現(xiàn)呢?  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗 2011-07-02 10:32 陳碩

@lijsf
UDP ?!  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗 2011-07-02 18:38 xLight

恩,理論題  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗 2011-07-07 22:26 放屁阿狗

ulimit一下,即使百萬也是沒有意義的,導(dǎo)致的結(jié)果就是每個fdset檢測時效率極低  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗[未登錄] 2012-05-13 12:03 lee

2**48是2的48次方,還是20048?  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗 2012-05-13 12:29 Solstice

@lee
前者  回復(fù)  更多評論   

# re: 關(guān)于 TCP 并發(fā)連接的幾個思考題與試驗[未登錄] 2012-05-13 14:16 lee

2的48次方,天文數(shù)字?。。Solstice
  回復(fù)  更多評論   

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

導(dǎo)航

統(tǒng)計

常用鏈接

隨筆分類

隨筆檔案

相冊

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            日韩视频在线观看国产| 亚洲麻豆一区| 久久综合色婷婷| 性欧美video另类hd性玩具| 亚洲午夜精品视频| 亚洲一区二区三区高清| 亚洲欧美大片| 久久精品免视看| 美女日韩在线中文字幕| 欧美国产日韩视频| 欧美视频四区| 国产精品网站在线| 伊人久久大香线| 99在线精品视频| 亚洲欧美日韩久久精品| 麻豆91精品| 亚洲人午夜精品| 亚洲视频免费| 久久久久久久久综合| 欧美久久久久久| 国产麻豆午夜三级精品| 亚洲高清在线播放| 亚洲一线二线三线久久久| 久久久久久久久综合| 亚洲国产一区二区三区高清| 亚洲图片欧洲图片av| 狼人天天伊人久久| 国产精品久久久久永久免费观看| 影音先锋日韩资源| 亚洲一区在线观看视频| 欧美3dxxxxhd| 午夜在线视频一区二区区别| 欧美极品aⅴ影院| 国产在线观看精品一区二区三区| 99在线热播精品免费| 老鸭窝91久久精品色噜噜导演| 最新日韩欧美| 久久深夜福利免费观看| 国产老肥熟一区二区三区| 亚洲三级国产| 另类亚洲自拍| 欧美一级片一区| 欧美日韩国产色综合一二三四| 伊伊综合在线| 久久久国产精彩视频美女艺术照福利 | 欧美日韩亚洲不卡| 亚洲欧美成人在线| 欧美激情视频免费观看| 国产亚洲精品久| 亚洲欧美国产另类| 9久re热视频在线精品| 欧美精品18| 亚洲精品免费网站| 欧美a级一区二区| 久久久久久97三级| 国产综合色精品一区二区三区 | 久久久人成影片一区二区三区观看 | 欧美电影电视剧在线观看| 国内精品福利| 久久久久久久性| 亚洲欧美美女| 国产精品超碰97尤物18| 在线亚洲一区| 一本色道久久综合亚洲精品按摩| 欧美日韩mp4| 中文在线资源观看网站视频免费不卡 | 国产欧美一区在线| 久久国产视频网| 欧美亚洲三区| 黄色av日韩| 欧美成人国产一区二区| 久久蜜桃精品| 亚洲麻豆一区| 在线播放豆国产99亚洲| 欧美中文在线视频| 久久精品国产久精国产一老狼| 国产欧美一区二区三区久久人妖| 久久久久www| 蜜桃伊人久久| 亚洲一区999| 欧美在线免费视屏| 亚洲经典一区| 亚洲图片激情小说| 黄色成人免费观看| 亚洲三级视频在线观看| 国产精品久久久久久av福利软件| 欧美一二三视频| 久久精品在线视频| 日韩视频一区二区| 亚洲一区二区综合| 亚洲国产三级| 在线亚洲+欧美+日本专区| 国产亚洲精品美女| 欧美福利视频| 国产精品萝li| 久久人人97超碰人人澡爱香蕉| 欧美高清在线精品一区| 亚洲综合欧美| 免费在线看成人av| 欧美sm视频| 久久精品视频在线看| 欧美高清视频在线| 欧美一级专区免费大片| 免费视频一区| 久久精品人人做人人综合| 欧美大片在线看免费观看| 午夜精品久久久久久久久久久久 | 日韩视频专区| 国产亚洲精品v| 亚洲日韩欧美视频一区| 狠狠爱综合网| 艳女tv在线观看国产一区| 136国产福利精品导航网址| 亚洲视频一区二区免费在线观看| 亚洲国产另类久久久精品极度| 亚洲综合色噜噜狠狠| 亚洲美女av网站| 美女999久久久精品视频| 欧美在线首页| 国产精品99免费看 | 亚洲肉体裸体xxxx137| 原创国产精品91| 久久成人精品电影| 亚洲一品av免费观看| 欧美激情亚洲自拍| 亚洲电影第三页| 影音先锋亚洲精品| 久久精品一区蜜桃臀影院| 欧美综合激情网| 国产精品色在线| 亚洲天堂偷拍| 亚洲女同同性videoxma| 欧美四级剧情无删版影片| 亚洲伦理久久| 亚洲一区二区三区视频播放| 欧美色播在线播放| 中国成人在线视频| 午夜影院日韩| 国产欧美日韩综合| 新狼窝色av性久久久久久| 欧美一区二区精品久久911| 国产精品一区二区三区观看| 亚洲欧美日韩国产综合| 久久精品国产清高在天天线| 国产亚洲aⅴaaaaaa毛片| 久久成人免费日本黄色| 久久人人爽人人爽爽久久| 一区二区视频在线观看| 老巨人导航500精品| 亚洲黄色在线观看| 亚洲在线观看| 国产亚洲女人久久久久毛片| 久久久久久国产精品mv| 欧美大片免费看| 蜜桃久久av| 欧美成人中文字幕| 亚洲国产婷婷| 亚洲一区二区三区视频播放| 国产精品久久久久婷婷| 午夜精品理论片| 女女同性精品视频| 一本色道久久88精品综合| 亚洲免费在线看| 老司机精品视频网站| 亚洲精品一二| 国产日本亚洲高清| 欧美~级网站不卡| 亚洲社区在线观看| 久久永久免费| 亚洲天天影视| 一区二区视频在线观看| 欧美视频中文字幕在线| 久久久噜噜噜久噜久久| 亚洲国产综合在线| 欧美在线一二三| 日韩视频一区二区三区在线播放免费观看 | 在线视频你懂得一区| 久久精品视频免费| 99热这里只有精品8| 国产亚洲精品7777| 欧美日韩精品是欧美日韩精品| 午夜久久久久久| 亚洲国产美国国产综合一区二区| 亚洲欧美日韩中文播放| 亚洲国产精品一区制服丝袜| 欧美性猛交xxxx乱大交蜜桃 | 亚洲最新视频在线| 欧美福利专区| 久久av老司机精品网站导航| 91久久极品少妇xxxxⅹ软件| 国产亚洲精久久久久久| 欧美色123| 欧美另类在线播放| 免费日韩视频| 久久久精品999| 欧美影视一区| 欧美一级视频精品观看| 一本色道久久88综合亚洲精品ⅰ| 免费观看欧美在线视频的网站| 欧美中文字幕第一页|