Linux TCP,如何調試寫入流的意外延遲?
問題:我的音樂伺服器程式碼使用阻塞套接字上的簡單 TCP 連接,需要將字節流式傳輸到客戶端(恰好是 Logitech 擠壓盒)。這並不復雜 - 從文件中讀取 64k,將其寫入擠壓箱,然後重複。它都在一個不忙的本地區域網路上執行,伺服器和squeezebox客戶端插入同一個交換機。擠壓盒不會很快消耗流,所以伺服器,在幾乎任何硬體上,都應該沒有問題保持客戶端的饋送。
而當伺服器執行在樹莓派 3B+ 上時,它實際上完全沒有問題。pi 零可能會跟上。當它在我的 Linux 筆記型電腦上執行時,同上,一切都很好。我可以定期詢問擠壓箱它的內部緩衝區有多滿,它很快就會達到大約 99+%,並保持在那裡。如您所料,伺服器 write()s(在前幾個之後)大部分時間都被阻塞了。
但是我將伺服器移動到執行 Linux 的 Azulle Inspire 上,插入同一個交換機,結果出現了可怕的錯誤。音樂開始播放,但很快就斷斷續續地消失了。擠壓箱報告緩衝區開始填滿,但隨後出現了一些問題,緩衝區迅速清空(有時會稍微增加一點,所以我認為有些流量通過了,但還不夠接近),音樂停止了。伺服器聲稱它正在繼續寫入,儘管寫入時間比我預期的要長。
請注意,Azulle 偶爾還有其他網路任務,它們都工作正常,儘管我可能不會注意到大多數其他應用程序的短暫網路延遲。但是當音樂伺服器執行時,NUC(和網路)處於空閒狀態——這不是 CPU 或頻寬問題。
我嘗試過更換電纜、更換開關並在開關上使用不同的埠。我試過發送不同的緩衝區大小。沒有效果。我能想到的只是 TCP 堆棧或乙太網硬體有一些非常不可靠的地方。
我該如何調試?流出來的 linux 筆記型電腦執行得很好,執行的是 Linux 4.15.0-55-generic(並且 apt upgrade 不會改變這一點)。Azuelle 執行的是 Linux 4.15.0-64-generic,Mint。我不敢相信 4.15.0 中的 TCP 處理髮生了根本性的變化。我對tcpdump之類的工具不是很熟悉,更不用說核心配置或調試了,所以我正在尋找一些手把手…
linux 筆記型電腦和 Azuelle 之間的 ping 時間始終在 0.2 毫秒和 0.35 毫秒左右,典型值為 0.33 毫秒。
我迷路了。TIA。
嗯,這就是我需要的線索。
當我對 MTU 大小感到好奇時,我發現了這一點:
/sys/class/net/enp1s0/mtu:1500/sys/class/net/lo/mtu:65536/sys/class/net/wlp2s0/mtu:1500
一切都很好,但 wlp 看起來像無線連接。無線的?那還開著嗎?所以我在 wlp… 界面上進行了 tcpdump,我看到了一條我從協議中辨識出來的消息,然後是一長串 ACK,沒有別的,流播放了幾秒鐘的音樂,但失敗了。
然後我關閉了無線並再次嘗試。沒有口吃。一切順利。
奇怪的是伺服器距離無線接入點只有幾英尺。即使它正在使用它,也不應該沒有足夠的頻寬。我想知道由於某種原因,同時打開兩者是否會導致問題,但我認為這是不可能的……
使用 tcpdump 擷取您的流:
tcpdump -i iface -s 1500 -w out.cap 'tcp and port xxx'
其中
iface
是網路介面,xxx
是兩個埠號之一。然後
out.cap
用wireshark打開,看看你能從trace中得到什麼。那裡發生了什麼應該很明顯。如果沒有,請再次發布。FWIW,從您所說的來看,這聽起來像是 MTU 問題。