【udp】關(guān)于 udp socket 連接問題分析

一茴迁、 udp問題抓包分析

公司內(nèi)部的一個 中間件報 UDP 連接異常的日志秽荞,問題很明顯,對端的服務(wù)掛了像捶,自然重啟下就可以了上陕。

讓人疑惑的問題是 udp 是如何檢測對端掛了?

err:  write udp 172.16.44.62:62651->172.16.0.46:29999: write: connection refused

err:  write udp 172.16.44.62:62651->172.16.0.46:29999: write: connection refused

err:  write udp 172.16.44.62:62651->172.16.0.46:29999: write: connection refused

UDP 協(xié)議既沒有三次握手作岖,又沒有 TCP 那樣的狀態(tài)控制報文唆垃,那么如何判定對端的 UDP 端口是否已打開?

通過抓包可以發(fā)現(xiàn)痘儡,當服務(wù)端的端口沒有打開時,服務(wù)端的系統(tǒng)向客戶端返回 icmp ECONNREFUSED 報文枢步,表明該連接異常沉删。

通過抓包可以發(fā)現(xiàn)返回的協(xié)議為 ICMP,但含有源端口和目的端口醉途,客戶端系統(tǒng)解析該報文時矾瑰,通過五元組找到對應(yīng)的 socket,并 errno 返回異常錯誤隘擎,如果客戶端陷入等待殴穴,則喚醒起來,設(shè)置錯誤狀態(tài)货葬。

(上面是 udp 異常情況下的 icmp采幌,下面是udp 正常 情況下的icmp)

image.png
image.png

寫UDP socket程序的時候,在調(diào)用sendto或者recvfrom的時候震桶,會發(fā)現(xiàn)有Connection refused錯誤返回休傍,錯誤碼是ECONNREFUSED。

對于懂得socket接口但是不很很懂網(wǎng)絡(luò)的人蹲姐,可能這根本就不是個問題磨取,他會根據(jù)錯誤碼知道遠端沒有這個服務(wù)端口,正如socket api的man手冊中描述的那樣:

ECONNREFUSED
A remote host refused to allow the network connection (typically because it is not running the requested service).

如果你十分精通TCP/IP棧柴墩,那么就想不通了忙厌,UDP既然無連接,怎么知道遠端的情況呢江咳?
UDP不正如協(xié)議標準描述的那樣逢净,發(fā)出去就不管了嗎?
對于接收,沒有數(shù)據(jù)就一直等汹胃,如果設(shè)置了NOWAIT婶芭,則直接返回EAGAIN,表示稍后再試着饥。不管怎么說犀农,也不會有ECONNREFUSED這么詳細的信息返回才對啊。

既然UDP不會從對端返回任何錯誤信息宰掉,那么一定有別的什么返回了呵哨,這就涉及到了網(wǎng)絡(luò)協(xié)議設(shè)計中的數(shù)據(jù)平面和控制平面了,對于控制平面的消息轨奄,可以是帶內(nèi)傳輸孟害,也可以是帶外傳輸。

數(shù)據(jù)分為兩種挪拟,一種是帶內(nèi)數(shù)據(jù)挨务,一種是帶外數(shù)據(jù)。
帶內(nèi)數(shù)據(jù)就是我們平常傳輸或者說是口頭叫的數(shù)據(jù)玉组,帶外數(shù)據(jù)就是我們接下來講的內(nèi)容谎柄。

許多的傳輸層都具有帶外數(shù)據(jù)(也稱為 經(jīng)加速數(shù)據(jù) )的概念,想法就是連接的某段發(fā)生了重要的事情惯雳,希望迅速的通知給對端朝巫。這里的迅速是指這種通知應(yīng)該在已經(jīng)排隊了的帶內(nèi)數(shù)據(jù)之前發(fā)送,也就是說石景,帶外數(shù)據(jù)擁有更高的優(yōu)先級劈猿。帶外數(shù)據(jù)可以使用一條獨立的傳輸層連接,也可以映射到傳輸普通數(shù)據(jù)的連接中潮孽。其中揪荣,UDP沒有實現(xiàn)帶外數(shù)據(jù)。

TCP中telnet恩商、rlogin和ftp等变逃,除了這樣的遠程非活躍應(yīng)用之外,幾乎很少有使用到帶外數(shù)據(jù)的地方怠堪。

TCP利用其頭部中的緊急指針標志以及緊急指針字段揽乱,給應(yīng)用程序提供里一種緊急方式,所以TCP是利用傳輸普通數(shù)據(jù)的連接來傳輸帶外數(shù)據(jù)粟矿。

對于TCP而言凰棉,無疑是帶內(nèi)傳輸?shù)模驗樗旧砭褪怯羞B接的協(xié)議陌粹,協(xié)議本身會處理任何的錯誤和異常撒犀,然而對于UDP而言,因為其設(shè)計目的就是保持簡單性,故不再附帶有任何帶內(nèi)的控制消息邏輯或舞,互聯(lián)網(wǎng)上為了彌補這一類協(xié)議的控制邏輯的缺失荆姆,ICMP協(xié)議才顯得尤為重要!

實際上映凳,ICMP胆筒,根據(jù)名稱就可以看出它是一種專門的控制協(xié)議,控制和指示IP層發(fā)生的事件诈豌。

ECONNREFUSED正是ICMP返回的仆救,然而并不是所有的UDP socket都可以享用ICMP帶來的錯誤提示,畢竟帶外控制消息和協(xié)議本身的關(guān)聯(lián)太松散了矫渔。
UDP socket必須顯式的connect對端才可以彤蔽。

現(xiàn)在問題又來了,既然UDP根本就是一個無連接的協(xié)議庙洼,connect的意義何在呢顿痪?
這其實是socket接口設(shè)計的范疇,和協(xié)議本身沒有任何關(guān)系油够,當一個UDP socket去 connect一個遠端時员魏,并沒有發(fā)送任何的數(shù)據(jù)包,其效果僅僅是在本地建立了一個五元組映射叠聋,對應(yīng)到一個對端,該映射的作用正是為了和UDP帶外的ICMP控制通道捆綁在一起受裹,使得UDP socket的接口含義更加豐滿碌补。

image.png

我們知道,ICMP錯誤信息返回時棉饶,ICMP的包內(nèi)容就是出錯的那個原始數(shù)據(jù)包厦章,根據(jù)這個原始數(shù)據(jù)包可以找出一個五元組,根據(jù)該五元組就可以對應(yīng)到一個本地的connect過的UDP socket照藻,進而把錯誤消息傳輸給該socket袜啃,應(yīng)用程序在調(diào)用socket接口函數(shù)的時候,就可以得到該錯誤消息幸缕。
如果一個UDP socket沒有調(diào)用過connect群发,那么即使有ICMP數(shù)據(jù)包返回,由于socket保持了UDP的完整語義发乔,協(xié)議棧也就不保存關(guān)于該socket和對端關(guān)聯(lián)的任何信息熟妓,因此也就無法找到一個特定的五元組將錯誤碼傳給它。

你不能太指望這個Connection refused以及一切帶外返回的錯誤信息栏尚,因為你不能保證一定能收到遠端發(fā)送的ICMP包起愈,如果中間的某個節(jié)點或者本機禁掉了ICMP,socket api調(diào)用就無法捕獲這些錯誤了。

當 UDP 連接異常時抬虽,可以通過 tcpdmp 工具指定 ICMP 協(xié)議來抓取該異常報文官觅,畢竟對方是通過 icmp 返回的 ECONNREFUSED。

我們使用 tcpdump 抓包阐污,先找到一個可以 ping 通的目標主機, 然后用 nc 模擬 udp 客戶端去請求不存在的端口休涤,出現(xiàn) Connection refused.

# yum  -y install  nc 

# nc -vzu 172.16.0.46 8888
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 172.16.0.46:8888.
Ncat: Connection refused.
# tcpdump   -i   any   icmp   -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
17:01:14.075617 IP 172.16.0.46 > 172.16.0.62: ICMP 172.16.0.46 udp port 8888 unreachable, length 37
17:01:17.326145 IP 172.16.0.46 > 172.16.0.62: ICMP 172.16.0.46 udp port 8888 unreachable, length 37
17:01:17.927480 IP 172.16.0.46 > 172.16.0.62: ICMP 172.16.0.46 udp port 8888 unreachable, length 37
17:01:18.489560 IP 172.16.0.46 > 172.16.0.62: ICMP 172.16.0.46 udp port 8888 unreachable, length 37

注意: telnet 不支持 udp,,只支持 tcp疤剑,建議使用 nc 來探測 udp滑绒。

二、各種case的測試

case小結(jié):

  1. 當 ip 無法連通時, udp 客戶端連接時隘膘,通常會顯示成功
  2. 當 udp 服務(wù)端程序關(guān)閉, 但系統(tǒng)還存在時, 對方系統(tǒng)會 icmp ECONNREFUSE 錯誤
  3. 當對方有操作 iptables udp port drop 時疑故,通常客戶端也會顯示成功.
# ping 172.16.0.65

PING 172.16.0.65 (172.16.0.65) 56(84) bytes of data.
From 172.16.0.46 icmp_seq=1 Destination Host Unreachable
From 172.16.0.46 icmp_seq=2 Destination Host Unreachable
From 172.16.0.46 icmp_seq=3 Destination Host Unreachable
From 172.16.0.46 icmp_seq=4 Destination Host Unreachable
From 172.16.0.46 icmp_seq=5 Destination Host Unreachable
From 172.16.0.46 icmp_seq=6 Destination Host Unreachable
^C
--- 172.16.0.65 ping statistics ---
6 packets transmitted, 0 received, +6 errors, 100% packet loss, time 4999ms
pipe 4

# nc   -zuv 172.16.0.65 8888
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 172.16.0.65:8888.
Ncat: UDP packet sent successfully
Ncat: 1 bytes sent, 0 bytes received in 2.02 seconds.

再次明確一點 udp 沒有類似 tcp 那樣的狀態(tài)報文, 所以單純對 UDP 抓包是看不到啥異常信息.
那么當 IP 不通時, 為啥nc udp 命令顯示成功 ?

netcat nc udp 的邏輯

為什么當 ip 不連通或者報文被 drop 時弯菊,返回連接成功 ?

因為 nc 默認的探測邏輯很簡單纵势,只要在 2 秒鐘內(nèi)沒有收到 icmp ECONNREFUSED 異常報文, 那么就認為 UDP 連接成功。

所以管钳, UDP 客戶端钦铁,給無法連通的地址發(fā) UDP 報文時,其實也不會報錯, 這時候通常會認為發(fā)送成功才漆。

還是那句話 UDP 沒有 TCP 那樣的握手步驟牛曹,像 TCP 發(fā)送 syn 總得不到回報時, 協(xié)議棧會在時間退避下嘗試 6 次,當 6 次還得不到回應(yīng)醇滥,內(nèi)核會給與錯誤的 errno 值黎比。

UDP 連接信息

在客戶端的主機上, 通過 ss lsof netstat 可以看到 UDP 五元組連接信息。

$ netstat  -tunalp | grep 29999

udp   0   0 172.16.0.46:44136  172.16.0.46:29999   ESTABLISHED 1285966/client

通常在服務(wù)端上看不到 UDP 連接信息, 只可以看到 udp listen 信息 鸳玩!

# netstat -tunalp|grep 29999

udp    0      0 :::29999     :::*     4038720/server

客戶端重新實例化問題 ?
當 client 跟 server 已連接阅虫,server 端手動重啟后,客戶端無需再次重新實例化連接不跟,可以繼續(xù)發(fā)送數(shù)據(jù)颓帝。當服務(wù)端再次啟動后,照樣可以收到客戶端發(fā)來的報文窝革。

udp 本就無握手的過程购城,他的 udp connect() 也只是在本地創(chuàng)建 socket 信息. 在服務(wù)端使用 netstat 是看不到 udp 五元組的 socket。

image.png
image.png

總結(jié)

當 udp 服務(wù)端的機器可以連通且無異常時聊闯,客戶端通常會顯示成功工猜。
但當有異常時,會有以下的情況:

  1. 當 ip 地址無法連通時, udp 客戶端連接時菱蔬,通常會顯示成功

  2. 當 udp 服務(wù)端程序關(guān)閉, 但系統(tǒng)還存在時, 對方系統(tǒng)通過 icmp ECONNREFUSE 返回錯誤仔夺,客戶端會報錯

  3. 當對方有操作 iptables udp port drop 時,客戶端也會顯示成功

4 客戶端和服務(wù)端互通數(shù)據(jù)医增,當服務(wù)進程掛了時头岔,UDP 客戶端不能立馬感知關(guān)閉狀態(tài),只有當再次發(fā)數(shù)據(jù)時才會被對方系統(tǒng)回應(yīng) icmp ECONNREFUSE 異常報文, 客戶端才能感知對方掛了。

三、參考

讓人迷糊的 socket udp 連接問題
https://xiaorui.cc/archives/7255

TCP/IP 某些最常見的錯誤原因碼 (errno)列表
https://www.cnblogs.com/jiu0821/p/5895723.html

技術(shù)分享之網(wǎng)絡(luò)編程的那些事兒
https://xiaorui.cc/archives/7271

TCP 帶外數(shù)據(jù)(即緊急模式的發(fā)送和接受)
https://blog.csdn.net/liushengxi_root/article/details/82563181

TCP帶外數(shù)據(jù)
https://www.cnblogs.com/c-slmax/p/5553857.html

TCP-帶外數(shù)據(jù)(緊急數(shù)據(jù))
http://www.reibang.com/p/65a4b8c059d4

什么是帶外管理和帶內(nèi)管理税朴?
https://zhuanlan.zhihu.com/p/341264872

FAQ-什么是帶外管理和帶內(nèi)管理?它們的區(qū)別是什么?
https://support.huawei.com/enterprise/zh/knowledge/EKB1000055297

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末家制,一起剝皮案震驚了整個濱河市正林,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颤殴,老刑警劉巖觅廓,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涵但,居然都是意外死亡杈绸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門矮瘟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瞳脓,“玉大人,你說我怎么就攤上這事澈侠〗俨啵” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵哨啃,是天一觀的道長板辽。 經(jīng)常有香客問我,道長棘催,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任耳标,我火速辦了婚禮醇坝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘次坡。我一直安慰自己呼猪,他們只是感情好,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布砸琅。 她就那樣靜靜地躺著宋距,像睡著了一般。 火紅的嫁衣襯著肌膚如雪症脂。 梳的紋絲不亂的頭發(fā)上谚赎,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天淫僻,我揣著相機與錄音,去河邊找鬼壶唤。 笑死雳灵,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的闸盔。 我是一名探鬼主播悯辙,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迎吵!你這毒婦竟也來了躲撰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤击费,失蹤者是張志新(化名)和其女友劉穎拢蛋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荡灾,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡瓤狐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了批幌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片础锐。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荧缘,靈堂內(nèi)的尸體忽然破棺而出皆警,到底是詐尸還是另有隱情,我是刑警寧澤截粗,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布信姓,位于F島的核電站,受9級特大地震影響绸罗,放射性物質(zhì)發(fā)生泄漏意推。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一珊蟀、第九天 我趴在偏房一處隱蔽的房頂上張望菊值。 院中可真熱鬧,春花似錦育灸、人聲如沸腻窒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽儿子。三九已至,卻和暖如春砸喻,著一層夾襖步出監(jiān)牢的瞬間柔逼,已是汗流浹背蒋譬。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卒落,地道東北人羡铲。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像儡毕,于是被迫代替她去往敵國和親也切。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

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