|
最近在公司寫了個基于UDP協(xié)議的日志收集服務(wù),邏輯很簡單,客戶端(PHP應(yīng)用)通過socket把數(shù)據(jù)發(fā)過來,服務(wù)端記錄日志并返回成功。由于開發(fā)測試時Server和Client都是同一臺機(jī)器上,一直平安無事。后來又找了臺機(jī)器想做一下壓力,卻發(fā)現(xiàn)無論如何Client都不到回包。通過tcpdump看,Server端的確已經(jīng)回包了,但Client機(jī)器上只能看到一個發(fā)包。 這個問題排查了整個下午,因為一直沒有頭緒。最初想到的是網(wǎng)絡(luò)原因,可能端口被防火墻攔截,但用nc試驗收發(fā)包,沒有問題,所以排除了網(wǎng)絡(luò)原因。然后懷疑是不是某些系統(tǒng)調(diào)用出問題了?寫了一段最簡單的udp收發(fā)包代碼,發(fā)現(xiàn)也沒有問題。然后懷疑是不是框架出問題了,打了一些點,重新編譯,也沒有發(fā)現(xiàn)異常,這時想到之前用同一個框架寫的服務(wù),找出來編譯運行,發(fā)現(xiàn)竟然可以正常收發(fā)包。然后我開始修改這個服務(wù)的發(fā)包部分,逐漸減少sendto的內(nèi)容,直到不行,這時開始懷疑是不是UDP包有最小長度限制。 因為日志服務(wù)邏輯簡單,返回內(nèi)容也很簡單,返回內(nèi)容包括開始結(jié)束標(biāo)識、請求序列號、結(jié)果字段,加起來才8個字節(jié)。這時我隨便增加幾個返回字節(jié),發(fā)現(xiàn)Client已經(jīng)可以正常收到回包,問題算是解決了。最后測試出UDP包長不能低于12個字節(jié),這其中不包括UDP自己的8個字節(jié)的頭部。 再用nc試驗,驗證了這個問題: (1)Server端,用nc監(jiān)聽5544端口,如果有請求則返回a.txt文件中的內(nèi)容,a.txt中是兩個字符;
(2)Client端,用nc給Server端發(fā)包;
(3)Server端的tcpdump,可以看到收到了包也回了包,回包長度length=2;
(4)Client端的tcpdump,只能看到發(fā)包,看不到回包。用netstat -us也沒有看到收包錯誤的增加。
(5)這時將Server端的返回增加到12個字節(jié)(文件末尾還有一個字節(jié)),可以看到Client端可以正常收到回包。
繼續(xù)查這個問題,發(fā)現(xiàn)有人說: “802.3 規(guī)定數(shù)據(jù)部分至少為38字節(jié),以太網(wǎng)最少要46字節(jié).不足的空間插入填充字節(jié).” 其中,IP頭部是20字節(jié)(包括雙方IP、長度、控制字段等),UDP頭部是8個字節(jié)(包括雙方端口、長度、校驗和),這兩個頭部占用了28個字節(jié)。 其他參考: TCP/IP詳解學(xué)習(xí)筆記(8)– UDP:用戶數(shù)據(jù)報協(xié)議 http://www.cnblogs.com/newwy/p/3227767.html IP數(shù)據(jù)包長度問題總結(jié) http://blog.csdn.net/naturebe/article/details/6712153 |
|
|