如何強制進程透過 UDP 而不是 TCP 進行傳輸?

如何強制進程透過 UDP 而不是 TCP 進行傳輸?

我正在 Linux 機器上運行 ffserver 進程,以便透過以下方式實現視訊串流ffmpeg。但是,視訊串流存在延遲。在ffserver設定檔我定義Port 8090.

命令netstat-tulnap給了我這個:

root@beagleboard:/etc# netstat -tulnap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             Stat                                                                             e       PID/Program name
tcp        0      0 0.0.0.0:68                  0.0.0.0:*                   LIST                                                                             EN      654/pump
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LIST                                                                             EN      662/portmap
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LIST                                                                             EN      698/dropbear
tcp        0      0 0.0.0.0:8090                0.0.0.0:*                   LIST                                                                             EN      744/ffserver
tcp        0     52 192.168.1.104:22            192.168.1.111:10838         ESTA                                                                             BLISHED 724/dropbear
udp        0      0 0.0.0.0:514                 0.0.0.0:*                                                                                                            703/syslog-ng
udp        0      0 0.0.0.0:111                 0.0.0.0:*                                                                                                            662/portmap
udp        0      0 0.0.0.0:60628               0.0.0.0:*                                                                                                            709/avahi-daemon: r
udp        0      0 0.0.0.0:5353                0.0.0.0:*                                                                                                            709/avahi-daemon: r

正如您所看到的,ffserver進程使用tcp協定進行傳輸,我懷疑這是視訊串流延遲的原因。如何強制進程使用 udp 協定?我應該更改連接埠嗎?

答案1

您不能只強製程式使用 UDP 而不是 TCP,而不重寫程式本身的部分內容。這些協定差異太大,無法互換。

  • TCP 是面向流的(接收方將所有內容視為連續流,其順序與發送方輸出的順序完全相同); UDP 是面向資料封包的(每個資料封包都在單獨的資料包中發送,甚至可以重新排序)。

  • TCP 具有流量控制,因此發送方(或發送方的作業系統)確切地知道應該以多快的速度發送數據,而不會導致鏈路溢出或顯著影響其他連接。 UDP 不會執行任何此操作 - 一個「強制」不良的程式可能會開始透過 UDP 每秒發送千兆位元組的數據,而不管連結速度如何。

  • TCP 具有重傳功能,因此如果封包在中間遺失(例如,由於網路過載或存在其他問題),則會重新傳送封包。如果協定依賴可靠的傳輸,並且您強制它通過 UDP,則一旦至少有一個資料包遺失,連線可能會完全中斷。 (和數據包將要迷路;參見上面#1 和#2 點。

答案2

正如其他人所提到的,UDP 和 TCP 是根本不同的協定。

但是,如果您必須透過 UDP 而不是 TCP 傳輸數據,您可以使用中繼工具,例如索卡特。您可以將 socat 配置為偵聽 TCP 連接,並將 TCP 流的內容作為 UDP 流轉送到另一台主機。如果另一台主機期望 TCP 流量,您可以使用那裡的另一個中繼實例將其轉換回 TCP。這將從主機到主機連結中刪除重試和確認行為。本地中繼工具和本地應用程式之間仍將存在重試和確認,但您不太可能在本地環回鏈路上看到重試。

但是,這不太可能解決您的延遲問題。如果您的應用程式建置為使用 TCP 而不是 UDP,則它可能無法容忍遺失的資料包,在這種情況下,此 hack 可能會導致不穩定的行為。

答案3

除非您使用的連線速度非常慢,否則延遲問題很可能是由於您的視訊編解碼器造成的。

要有效地壓縮視頻,您必須使用預測編碼(請參閱維基百科上的這篇文章)。

預測編碼基本上是根據較早或較晚的圖像計算圖像。這具有以下含義:

  1. 如果您使用許多 P 幀(根據較早的幀計算),則在視訊顯示之前會出現延遲開始,因為客戶端必須等待下一個完整視訊幀(I 幀)。但是,一旦建立串流,您就可以相對無延遲地觀看影片。

  2. 如果您使用B 幀(根據較早和較晚的圖像計算),則會出現一些非常大的延遲:除了上面的初始延遲之外,客戶端還必須等待下一個I 幀才能從最後一個I 幀開始播放。這會導致延遲(客戶端播放視頻明顯晚於伺服器記錄/發送視頻,通常是很多秒)。如果您動態編碼視頻,伺服器也會有延遲 - 它需要等待下一個 I 幀才能發送從上一個 I 幀開始的所有內容。

對於大多數編解碼器,您可以根據需要調整 B 幀和 P 幀的使用,但是,需要在延遲與壓縮效率之間進行權衡

如果您有足夠的頻寬,您也可以使用沒有 B-/P-幀的編解碼器,例如MJPEG

延遲的另一個原因是播放器端的緩衝,因此即使網路傳輸不穩定,也不會出現任何失真。許多視訊播放器允許您調整緩衝區大小。

相關內容