如何强制进程通过 UDP 而不是 TCP 进行传输?

如何强制进程通过 UDP 而不是 TCP 进行传输?

我在 Linux 机器上运行 ffserver 进程,以便通过以下方式实现视频流ffmpeg。但是,视频流有延迟。ffserver 配置文件我定义Port 8090

命令网络状态监测给了我这个:

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 每秒发送数 GB 的数据,而不管链路速度如何。

  • TCP 具有重传功能,因此如果数据包在中途丢失(例如由于网络过载或其他问题),它将被重新发送。如果协议依赖于可靠的传输,并且您强制它通过 UDP 传输,那么一旦至少一个数据包丢失,连接就可能完全中断。(并且数据包将要迷路;参见上面的第 1 点和第 2 点。)

答案2

正如其他人提到的,UDP 和 TCP 是根本不同的协议。

但是,如果你必须通过 UDP 而不是 TCP 传输数据,你可以使用中继工具,例如索卡特。您可以配置 socat 来监听 TCP 连接,并将 TCP 流的内容作为 UDP 流转发到另一台主机。如果另一台主机正在等待 TCP 流量,您可以使用那里的另一个中继实例来转换回 TCP。这将从主机到主机链接中删除重试和确认行为。本地中继工具和本地应用程序之间仍将存在重试和确认,但您不太可能在本地环回链接上看到重试。

但是,这不太可能解决您的延迟问题。如果您的应用程序是使用 TCP 而不是 UDP 构建的,它可能无法容忍丢包,在这种情况下,这种黑客行为可能会导致不稳定的行为。

答案3

除非您使用的连接速度非常慢,否则延迟问题很可能是由于您的视频编解码器造成的。

为了有效地压缩视频,你必须使用预测编码(参见维基百科上的这篇文章)。

预测编码基本上是根据较早或较晚的图像来计算图像。这具有以下含义:

  1. 如果你使用许多 P 帧(从较早的帧计算),视频显示之前会有一些延迟开始,因为客户端必须等待下一个完整视频帧(I 帧)。但是,一旦建立流,您就可以相对无延迟地观看视频。

  2. 如果您使用 B 帧(根据较早和较晚的图像计算),您将会遇到一些非常大的延迟:除了上面的初始延迟之外,客户端还必须等待下一个 I 帧才能从最后一个 I 帧开始播放。这将导致延迟(客户端播放视频的时间明显晚于服务器记录/发送视频的时间,通常要花很多秒)。如果您正在即时编码视频,您还会遇到来自服务器的延迟——它需要等待下一个 I 帧才能从上一个 I 帧开始发送所有内容。

对于大多数编解码器,您可以根据需要调整 B 帧和 P 帧的使用,但是,这需要在延迟和压缩效率之间做出权衡

如果你有足够的带宽,你也可以使用没有 B/P 帧的编解码器,例如图像处理

造成延迟的另一个原因是播放器端的缓冲,因此如果网络传输不稳定,您不会遇到任何失真。许多视频播放器允许您调整缓冲区大小。

相关内容