从理论上讲,没有什么能阻止将 TCP 套接字与 SOCK_DGRAM 一起使用。您将获得可靠的数据报传输。这可能使用伯克利插座吗?
6 回答
您要查看的是SCTP 协议。它提供了通过可靠的 TCP 样式连接发送数据报的能力:
与 TCP 相比,SCTP 可以表征为面向记录,这意味着它以消息的形式传输数据,与用户数据报协议 (UDP) 类似,因此在一次传输操作中发送一组字节(消息) (记录)在接收方应用程序中被准确地读取为该组。TCP 是面向流的,传输字节流,它在无序交付的情况下正确地重新排序。然而,它不尊重消息边界,即在发送方的原始传输单元方面的数据结构。
查看 SCTP 一对一样式的连接,这可能是您正在寻找的。
大多数 Unix/Linux 操作系统都有实现,Windows 也有第三方实现。有关详细信息,请参阅我链接的 Wiki 文章的末尾。
SOCK_DGRAM 作为类型为您提供 UDP 套接字。您当然可以将 UDP 封装在 TCP 中,但您必须在用户空间中处理 UDP 部分。某事是否可靠取决于线路上的协议。如果使用TCP,则可靠;UDP不是。
创建 UDP 套接字:
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
创建 TCP 套接字:
int s;
s = socket(AF_INET, SOCK_STREAM, 0);
有两种常见的方法可以通过线路发送离散的数据块。您可以使用 UDP 并将离散块作为数据报发送,也可以将结构构造成 TCP 数据,然后将它们作为流发送。使用 TCP 通常更简单且不易出错。如果您使用 UDP,只需超时并继续请求相同的数据,直到您得到它。
从理论上讲,没有什么能阻止将 TCP 套接字与 SOCK_DGRAM 一起使用。您将获得可靠的数据报传输。这可能使用伯克利插座吗?
不,Berkeley API 提供不可靠的数据报或可靠的流。
如果您想通过 TCP 发送可靠的块,请使用一些将流拆分为块的协议。这很简单。
我还没有看到任何为您提供此选项的套接字 api - 它也会破坏 TCP 让您控制数据对齐的某些目的。TCP 只是传输,它的抽象是字节流。
您将必须在 TCP 之上构建自己的消息结构,从而为您提供应用层关心的消息概念。
并不真地。TCP 和 UDP 是来自同一层的协议,它们具有仅对它们有意义的功能。以listen() 和accept() 为例。
您可以在 TCP 数据包中发送 UDP 标头+数据,但根本没有意义。为什么要这么做?一种隧道?实际上,手动解析和构建 UDP 数据包非常容易,但我在您的场景中没有看到真正的应用程序。
您可以模拟事物,但实际上没有理由这样做。您要么想要可靠的交付,要么想要及时交付。TCP给你第一个,UDP给你第二个。两者不能混用,因为 TCP 通过反复告诉另一端消息直到它们被确认来实现可靠性。对于流式传输,您通常需要可靠的数据传输(因此您可以重新组装流),但对于顺序不重要的小消息(即数据报),您不需要所有开销(UDP 确实在很大程度上保证消息在至少不会出现乱码;这是 TCP 和 UDP 通过原始 IP 提供的东西之一)。
当然,这两个极端之间还有一些其他有趣的案例。对于实时流式传输数据(例如,视频通话),您使用RTP是因为您正在流式传输,但可以比延迟更好地从数据丢失中恢复。对于对于 UDP 来说太大的消息(64kB 是严格的上限,因为 UDP 标头的长度字段只有 16 位),您几乎需要使用 TCP 进行传输,以便您可以重新组装片段(因此SOAP 通过 TCP 上的 HTTP,而不是通过 UDP)。