【问题标题】:Are TCP/IP Sockets Atomic?TCP/IP 套接字是原子的吗?
【发布时间】:2017-09-10 03:30:36
【问题描述】:

据我了解,如果写入的数据量很小,则对 TCP/IP 套接字的写入将是原子的。原子,我的意思是接收者将接收所有数据或不接收任何数据。但是,如果写入的数据量很大,它就不是原子的。我对么?如果是,什么算大?

谢谢, 鲍勃

【问题讨论】:

  • Bob,你的问题很好,很多程序员都有这样的错误,他们认为如果他们在 TCP 套接字中发送 N 字节,另一个节点将读取所有 N 字节。然后,他们运行功能测试并工作。但是,这是一个会在某个时刻在系统中产生故障的错误。你要做的是创建一个简单的应用层协议,通常是 TLV(Type, Length, Value)。我在这里解释一下(这个问题对任何编程语言都有效):stackoverflow.com/questions/19839172/…

标签: sockets tcp network-programming


【解决方案1】:

对于 UDP,确实如此,因为应用程序写入的所有数据都在一个 UDP 数据报中发送出去。

对于 TCP,这是不正确的,除非应用程序一次只发送 1 个字节的数据。对 TCP 套接字的写入会将所有数据写入与该套接字关联的缓冲区。然后 TCP 将在后台从该缓冲区读取数据并将其发送到接收器。 TCP 在一个 TCP 段中实际发送多少数据取决于其流量控制机制的变量以及其他因素,包括:

  • 其他节点(接收方)发布的接收窗口
  • 在之前的飞行航段中发送但尚未确认的数据量
  • 慢启动和拥塞避免算法状态
  • 协商的最大分段大小 (MSS)

在 TCP 中,您永远不能假设应用程序写入套接字的内容实际上是在一次读取中被接收者接收的。套接字缓冲区中的数据可以通过一个或多个 TCP 段发送到接收方。在数据可用的任何时刻,接收器都可以执行套接字读取并返回当时实际可用的任何数据。

当然,所有发送的数据最终都会到达接收者,如果中间没有故障阻止,并且接收者没有在数据到达之前关闭连接或停止读取。

【讨论】:

  • 除非应用程序一次只发送 1 个字节的数据”——即使这样也不能保证,因为默认情况下会缓冲数据。您可以执行多个 1 字节写入,并且仍然在单个 TCP 段中将它们一起发送出去,除非您启用 TCP_NODELAY 套接字选项。
  • 而且在任何情况下,您仍然可以在一次接收操作中接收它们。 @RemyLebeau
  • @EJP:是的,如果在应用程序执行新的读取操作之前在套接字中接收并缓冲了多个 TCP 段。
  • @RemyLebeau 和 EJP,这是正确的!许多 1 字节写入可能仅在一个段中发送。接收应用程序可能会在一个或多个读取操作中读取它们。谢谢你的澄清。
【解决方案2】:

没有。 TCP 是一种字节流协议。没有消息,没有类似数据报的行为。

【讨论】:

  • 根据我收到的响应,如果服务器写入一个四字节整数,而客户端读取一个四字节整数,则读取可能只返回两个字节,因为写入不是原子的,后续读取然后将返回另外两个字节。我有这个权利吗?鲍勃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-13
  • 2010-09-15
  • 2017-01-02
  • 2011-05-12
  • 1970-01-01
  • 2011-10-01
相关资源
最近更新 更多