【问题标题】:For TCP, does returning from "write()" mean that the peer app has "read()" the data?对于 TCP,从“write()”返回是否意味着对等应用程序具有“read()”数据?
【发布时间】:2018-07-24 15:35:44
【问题描述】:

我正在编写一个 C/S 程序,客户端和服务器都可以在任意时间向对等方发送数据(没有明确的确认)。我想知道如果客户端和服务器巧合地同时写入对等方是否可能会死锁。

那么从write() 返回是否意味着对等应用程序已经拥有read() 数据?或者它仅仅意味着对等体的内核已经获得了数据并且将在下一个read()传递给应用程序?


(EJP 的回答修正了我对 write()/send()/... 的完全错误理解。为了添加一些权威信息,我在 POSIX 标准中发现了这个关于 send 的信息:

成功完成对 send() 的调用并不能保证消息的传递。返回值 -1 表示仅本地检测到的错误。

Linux 的关于send() 的手册页不是很清楚:

在 send() 中没有隐含发送失败的指示。本地检测到的错误由返回值 -1 指示。

或者是因为作为非英语母语人士,我无法完全理解第一句话。 )

【问题讨论】:

    标签: c sockets tcp network-programming


    【解决方案1】:

    我想知道如果客户端和服务器巧合地同时写入对等点,是否可能会死锁。

    它不能,除非其中一个或两个对等方的读取速度非常慢并且已经关闭了它的接收窗口。 TCP 是全双工的。

    那么从 write() 返回是否意味着对等应用程序已经 read() 数据?

    没有。

    或者它仅仅意味着对等体的内核已经获得了数据并会在下一次 read() 时传递给应用程序?

    没有。

    表示数据已到达您的内核,正在排队等待传输。

    write()返回表示TCP ACK已经收到。

    不,它没有。

    你的意思是从write()返回仅仅意味着数据已经到达发送者的内核?

    这不仅是我的意思,也是我所说的。

    我认为发送方已经收到了 TCP ACK,因此到达了对等方的内核。

    没有。

    【讨论】:

    • "数据已经到达你的内核"——你的意思是从write()返回仅仅意味着数据已经到达sender 的内核?我认为发送方已经收到 TCP ACK,因此到达了对等方的内核。
    • @pynexj 你错了。甚至不能保证数据已经发送,更不用说 ACK 了。如果您认为自己知道答案,为什么要问这个问题?
    • 不是我知道答案。我的理解是它已经达到了同行的内核。我不知道对方的应用程序是否调用了 read()。听起来我的整个理解都是错误的。
    • @pynexj 从write 返回意味着发送者能够将数据存储在传输黄油中。如果缓冲区已满,write 将被阻塞并稍后返回。否则它会立即返回。如果对方在接受连接后直接烧成灰烬,您的write 调用也会成功返回。
    • @pynexj 我同意你的看法。这是一个措辞不佳且最晦涩难懂的声明。他们想说的是,未能传递 this 数据不一定表示为 this 调用 send() 的返回值/errno,因为缓冲和所有其他问题。您最终会在随后的send()recv() 上收到与此数据相关的错误,但这可能需要一些时间。为什么他们不只是改编 Posix 文本或原始 BSD 文本,是另一个谜。
    【解决方案2】:

    没有。如果您将其视为数据管道,则从write 返回意味着您的数据已进入管道,不是它已从另一端退出管道。

    事实上,由于管道是数据可能采用数百种不同路径中的任何一种的管道,因此您甚至无法保证它到达另一端 :-) 如果发生这种情况,您将在稍后的某个日期收到通知,可能是通过 后续 write 失败。

    可能会被屏蔽:

    • 由于电缆损坏而试图退出您的机器,
    • 在某处路径的瓶颈处,
    • 通过目标的网络堆栈,
    • 通过网络路径中某些设备上的网络堆栈,比简单的集线器更智能,
    • 因为另一端的应用程序被绑定,
    • 等等。

    write 成功返回意味着您的本地网络堆栈已接受您的数据并将在适当的时候对其进行处理。

    【讨论】:

    • “由于电缆损坏,它可能在试图退出您的机器时被阻止,它可能在某处路径的瓶颈处被阻止” - 这是不可能的,因为从write() 返回意味着 TCP ACK 已经收到。所以它更像是在对等体的内核和应用程序之间的管道。
    • @pynexj 这没有任何意义。你是问还是说?
    • 正如我在 EJP 的回答中评论的那样,我的理解是它已经到达了同行的内核。我不知道对方的应用程序是否调用了 read()。听起来我的整个理解都是错误的。
    • 对不起,我没有意识到这是 EJP 在这里询问。 :)
    • 为了补充@EJP 已经正确解释的内容,想想如果每个 write() 调用都必须等到对等方收到 ACK 才能返回,下载速率会发生什么。想象一个高带宽,但也有高延迟的连接,例如。卫星链接...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2018-11-16
    • 2011-08-14
    • 2012-05-31
    • 2010-09-19
    • 1970-01-01
    相关资源
    最近更新 更多