2010-06-22 50 views

回答

2

的.Net为您处理数据的分裂。您可以编写并接收大于SendBufferSize的包,而不会发现它(如果您不太关心性能)。

1

你的协议中需要一个名为message framing的东西。有趣的事实:即使发送的信息小于SendBufferSize,您也需要这个。 :)

0

很可能您的数据将在接收时拆分,因此您需要在收到所有数据后重新构建数据。

3

与例如, UDP,TCP不是允许发送单个“消息”的协议,它以相同的形式发送到接收器。您宁愿发送和接收字节流。

引擎盖下,你的数据会分成的IP数据包,无论SendBufferSize,这顺便说一句默认为8192,(比适合单个IP包高得多的值的IP数据包的最大尺寸为相关MTU,但大部分少于1500字节)。例如:

  1. Socket.Send(2000个字节)
  2. IP分组#1(1460个字节)
  3. IP分组#2(540个字节)

另外:多个Socket.Send()的数据s可能会合并(Nagle's algorithm)。例如:

  1. Socket.Send(1000个字节)
  2. Socket.Send(1000个字节)
  3. IP分组#1(1460个字节)
  4. IP分组#2(540个字节)

接收器无法区分这两种情况。另外,出于效率原因,在接收端,数据可能会以不同大小的缓冲区传递给您。底线:使用TCP,您不能依靠接收的数据包与发送的数据包大小相同并且大小相同。如果您需要,请按照Stephen Cleary的建议添加大小信息,或者使用UDP等协议或者需要可靠性:SCTP。看起来像是过度杀毒,除非你对SCTP对TCP的其他改进感兴趣。

4

TCP不是仅限消息的协议。这是一个基于流的协议,负责为我们分割数据。让我把你带到核心部分。在TCP中有两部分 - 分段和分段。

分段发生在TCP(传输层)。这取决于两个参数 - MSS和窗口大小。 MSS确定设备可以接收的最大段数。 MSS在初始连接建立期间通过TCP选项进行通信。数据流的每个方向都可以使用不同的MSS,操作系统可以确定它。但是,窗口大小由接收方在TCP报头中发送,以便在等待来自接收主机的确认和窗口更新之前,一次在连接的接收端传送它可以缓冲的最大数据量。也就是说,主机可以在耗尽接收机窗口大小之前发送多个分段(MSS因子)。

碎片发生在IP(网络层)两种方式。如果在发送方和接收方之间的通信路径上没有MTU限制的设备,则分段将单独满足以太网(1500字节)的MTU。然而,在发送者和接收者之间存在具有MTU限制的中间设备时,IP层(因特网协议)进行数据报分片,使得分组可以形成为使得它们可以通过具有较小最大传输单元的链路MTU)比原始数据报大小。在具有MTU限制的中间设备的情况下,发送方还应该部署路径MTU发现以确定朝向接收方的网络路径中的最小MTU,并动态调整MSS以避免网络内的IP分段。路径MTU发现是通过在传出数据包的IP报头中设置DF(不分片)选项完成的。发送方和接收方之间的通信路径中的任何MTU小于数据包的通信路径都会丢弃这些数据包,并用包含该设备MTU的ICMP“Destination Unreachable(Datagram Too Big)”消息回复发送方。此信息允许发送方适当减少其假定的路径MTU。

因此,这导致了MSS和MTU之间的关系点。 RFC 791指出:“所有主机必须准备接受高达576个八位字节的数据报(无论它们是全部还是分段)”。因此,IP网络的最小MTU是576.在TCP的情况下,扣除TCP报头20个字节和IP报头20个字节,我们将为我们提供536个字节作为TCP的标准MSS。

现在,让我们进入重新组装的部分。碎片可能基于中间设备上的MTU发生,但重新组装只能在目标设备上进行。 TCP负责分段处理,但是在目标设备上,TCP需要负责排序,但是应用程序应该重新组合这些段。因此,如果您只需要基于整个消息的通信并且不需要考虑可靠性,那么UDP就是您的选择。但是,请注意,如果您可以通过拆分发送大量数据,则UDP将无法确保数据包的排序,并且无法处理数据包丢失,因为它不具有重新传输等纠错机制。

如果您想要进行基于消息的通信,就像在UDP中一样,但要配合TCP功能,如可靠的按序传送,拥塞控制以及其他改进/功能(如多流,归属,内置MTU发现,那么SCTP应该是您的选择。但是,如果您的网络中有传统的NAT系统,那么您可能需要在UDP中封装SCTP。