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

2021-06-01 11:39:49 +08:00
 FreeWong

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

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

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

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

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

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

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

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

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



我给你发送了一张图片。

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

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

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

我删除了这张图片。

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

抱歉!你的连接超时了。我给你发送了...哦不,图片不存在。
jedihy
2021-06-02 09:46:31 +08:00
跟 tcp 没关系。服务器应用层可以一直重试直到收到客户端的确认。
julyclyde
2021-06-02 10:56:35 +08:00
你这事其实都不需要可靠性
弱一致性甚至不一致都没啥损害

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/780562

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX