【发布时间】:2011-09-09 23:12:16
【问题描述】:
我有一个接收视频流的 tcp 套接字。我想从套接字逐包接收数据,以便我可以删除数据包头并保留唯一的流数据。我该怎么做??
任何帮助将不胜感激。
【问题讨论】:
-
“数据包”是什么意思?如果您正在谈论 IP 数据包,那已经为您完成了。还是您的意思是您的视频流协议使用了一些通过 TCP 发送的更高级别的数据包?
我有一个接收视频流的 tcp 套接字。我想从套接字逐包接收数据,以便我可以删除数据包头并保留唯一的流数据。我该怎么做??
任何帮助将不胜感激。
【问题讨论】:
你不能。 TCP 不适用于数据包/消息等。TCP 适用于 bytes。你得到一个字节流。问题是无法保证每次从套接字读取时获得的字节数。通常的处理方式:
您的信息可能是:
|Message Length:4bytes|Additional header Information:whatever1|Message Data:whatever2|
然后您要做的是读取 4 个字节,然后 然后 读取这 4 个字节告诉您的内容。然后你就可以剥离标题并获取数据了。
【讨论】:
tap接口(OpenVPN甚至有windows tap接口),实现自己的TCP协议栈,并提供带有@987654325的API @ 对数据包的可见性;但这是一项非常艰巨的工作。
SCTP。实现 TCP 堆栈在许多方面都比在操作系统中实现其他所有内容要困难。
正如其他人所提到的,TCP 是一种流协议。这意味着从 API 的角度来看,没有“数据包”的概念。作为用户,您所能期待的只是数据流。
在内部,TCP 会将流分成可以放入 IP 数据包的段。这些数据包将与控制数据一起通过 IP 发送到远程端。对端会收到这些IP包。它可能会丢弃某些 IP 数据包(在重复的情况下)、重新排序数据包或保留数据,直到较早的数据包到达。所有这些都是 TCP 内部的,这意味着“TCP 数据包”的概念是没有意义的。
您也许可以使用原始套接字来接收原始 IP 数据包,但这意味着您必须重新实现大部分 TCP 堆栈(例如发送 ACK 和调整窗口大小)才能使远程端正确执行。你不想这样做。
另一方面,UDP 是一种数据报协议。这意味着用户知道数据是如何通过网络发送的。如果数据包或数据报的概念对您很重要,您将需要在 UDP 之上构建自己的协议。
【讨论】:
TCP 是一种流协议,它不保证当您调用套接字读取函数时您将收到一个完整的数据包。 UDP 或 SCTP 是面向数据包的协议并保证这一点。对于 TCP,您可以一次获取部分数据包或少量数据包。您必须在 TCP 之上构建自己的应用程序协议,并手动对消息进行分段/碎片整理。
【讨论】:
TCP 是一种流协议。你得到没有消息边界的字节。解决方案是缓冲所有读取并从缓冲区中提取/处理完整的视频数据包。
算法:
recv() 的数据附加到缓冲区并转到 #2。“完整数据包”包含的内容应由视频流协议定义。
【讨论】:
您对这种方法很确定吗?在我看来,这些“预处理”会给系统带来额外的开销。当然,这是由较低层处理的(阅读有关 OSI 模型的信息),因此不容易更改。请注意,大多数现有的流式传输协议已经针对最佳性能进行了优化。
【讨论】: