V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
FreeWong
V2EX  ›  问与答

========= TCP 数据可靠性问题 ===========

  •  
  •   FreeWong · 2021-06-01 11:39:49 +08:00 · 1436 次点击
    这是一个创建于 1296 天前的主题,其中的信息可能已经有所发展或是发生改变。

    第 1 步 为了保证在应用层数据不丢失,我写的客户端程序发送一张图片时,除了包含这张图片的二进制数据以外,还会包含图片在磁盘上的文件名称

    第 2 步 当 TCP 服务器接收到图片并且成功保存到服务器磁盘后,会发送一条指令到 TCP 客户端(长连接的),其中里面包含刚才成功保存的图片文件名

    第 3 步 此时客户端接收到这条指令后,就从客户端的磁盘删除此图片

    前面三步,希望可以确保从客户端传输到服务器的图片不会丢失,仅当客户端收到服务器的接收图片成功的应答后,才会从客户端删除 但是,如果服务器成功接收到了,但是这个 成功接收后的 指令,也就是第 3 步中的数据 没有到达客户端怎么办呢?

    11 条回复    2021-06-02 10:56:35 +08:00
    malusama
        1
    malusama  
       2021-06-01 12:19:48 +08:00
    客户端超时会重试啊
    Jooooooooo
        2
    Jooooooooo  
       2021-06-01 15:40:03 +08:00
    搜一下 tcc 之类的东西
    ysc3839
        3
    ysc3839  
       2021-06-01 16:23:33 +08:00
    没有办法,服务器要确保客户端收到的话,就得让客户端回复一个确认收到的消息,但是这个确认收到的消息也有可能丢失,所以服务器收到后又得向客户端发送确认,最终会变成无限循环。
    GoLand
        4
    GoLand  
       2021-06-01 16:57:37 +08:00
    整个流程如果都是基于 TCP 通信的,那其实不需要做额外的事了。TCP 本身就保证可靠传输。

    至于你说的第三步的数据,客户端没有收到怎么办,这个完全想多了。你服务端应用层尽管往发送缓冲区写,客户端尽管从接收缓冲区读,数据没收到 TCP 会重传,不用你应用层操心。

    如果你担心 TCP 传输过程中出问题,你可以做本地事务表,定期去从服务器拉,服务器返回成功了客户端就删掉。

    这其实算是个分布式事务问题了。
    snw
        5
    snw  
       2021-06-01 17:14:49 +08:00 via Android
    只靠 TCP 重传好像会有问题。万一网络卡住的时间里,客户端这张图片被修改,或者这张图片被同名文件覆盖,等到你 TCP 重传成功后,会导致客户端的新图片被删除。
    iyaozhen
        6
    iyaozhen  
       2021-06-01 17:22:36 +08:00
    你把 tcp 当成黑盒,这个简单来说就是事务的问题,没收到 ack (情况很多,比如就是丢包了,服务收到图片后挂了),这个时候客户端就当没有传成功,再重试呗
    timethinker
        7
    timethinker  
       2021-06-01 17:24:33 +08:00
    先不考虑是否长连接,如果你用 HTTP 来做,那么当你在发起请求之后,网络断开了,此时你是处于未知状态的。保存有可能成功,也有可能失败。

    你可以在发起请求的时候创建一个唯一的 ID,这样服务器就可以支持幂等操作,你可以随意重新尝试 N 次,但是服务器只会处理一次。这样当你丢失连接以后,你可以随意再次发起一次请求,只有当你明确收到服务器的响应说这个请求已经处理完的时候,此时你再删除本地的文件。
    xiangyuecn
        8
    xiangyuecn  
       2021-06-01 17:29:13 +08:00
    确实是一个分布式事务 另外:这些功能基本不需要扯上 tcp 吧,顶多发个请求收个响应,不需要骑个自行车还要自己修条马路😂
    xieqiqiang00
        9
    xieqiqiang00  
       2021-06-01 23:01:25 +08:00
    想到了那个 TCP 笑话:



    我给你发送了一张图片。

    我收到了一张图片并且已经保存了。

    好的,我要在我这里删除这张图片。

    好的,你可以删除这张图片。

    我删除了这张图片。

    我知道了删除了这张图片。

    抱歉!你的连接超时了。我给你发送了...哦不,图片不存在。
    jedihy
        10
    jedihy  
       2021-06-02 09:46:31 +08:00
    跟 tcp 没关系。服务器应用层可以一直重试直到收到客户端的确认。
    julyclyde
        11
    julyclyde  
       2021-06-02 10:56:35 +08:00
    你这事其实都不需要可靠性
    弱一致性甚至不一致都没啥损害
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5059 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:48 · PVG 11:48 · LAX 19:48 · JFK 22:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.