第 1 步 为了保证在应用层数据不丢失,我写的客户端程序发送一张图片时,除了包含这张图片的二进制数据以外,还会包含图片在磁盘上的文件名称
第 2 步 当 TCP 服务器接收到图片并且成功保存到服务器磁盘后,会发送一条指令到 TCP 客户端(长连接的),其中里面包含刚才成功保存的图片文件名
第 3 步 此时客户端接收到这条指令后,就从客户端的磁盘删除此图片
前面三步,希望可以确保从客户端传输到服务器的图片不会丢失,仅当客户端收到服务器的接收图片成功的应答后,才会从客户端删除 但是,如果服务器成功接收到了,但是这个 成功接收后的 指令,也就是第 3 步中的数据 没有到达客户端怎么办呢?
1
malusama 2021-06-01 12:19:48 +08:00
客户端超时会重试啊
|
2
Jooooooooo 2021-06-01 15:40:03 +08:00
搜一下 tcc 之类的东西
|
3
ysc3839 2021-06-01 16:23:33 +08:00
没有办法,服务器要确保客户端收到的话,就得让客户端回复一个确认收到的消息,但是这个确认收到的消息也有可能丢失,所以服务器收到后又得向客户端发送确认,最终会变成无限循环。
|
4
GoLand 2021-06-01 16:57:37 +08:00
整个流程如果都是基于 TCP 通信的,那其实不需要做额外的事了。TCP 本身就保证可靠传输。
至于你说的第三步的数据,客户端没有收到怎么办,这个完全想多了。你服务端应用层尽管往发送缓冲区写,客户端尽管从接收缓冲区读,数据没收到 TCP 会重传,不用你应用层操心。 如果你担心 TCP 传输过程中出问题,你可以做本地事务表,定期去从服务器拉,服务器返回成功了客户端就删掉。 这其实算是个分布式事务问题了。 |
5
snw 2021-06-01 17:14:49 +08:00 via Android
只靠 TCP 重传好像会有问题。万一网络卡住的时间里,客户端这张图片被修改,或者这张图片被同名文件覆盖,等到你 TCP 重传成功后,会导致客户端的新图片被删除。
|
6
iyaozhen 2021-06-01 17:22:36 +08:00
你把 tcp 当成黑盒,这个简单来说就是事务的问题,没收到 ack (情况很多,比如就是丢包了,服务收到图片后挂了),这个时候客户端就当没有传成功,再重试呗
|
7
timethinker 2021-06-01 17:24:33 +08:00
先不考虑是否长连接,如果你用 HTTP 来做,那么当你在发起请求之后,网络断开了,此时你是处于未知状态的。保存有可能成功,也有可能失败。
你可以在发起请求的时候创建一个唯一的 ID,这样服务器就可以支持幂等操作,你可以随意重新尝试 N 次,但是服务器只会处理一次。这样当你丢失连接以后,你可以随意再次发起一次请求,只有当你明确收到服务器的响应说这个请求已经处理完的时候,此时你再删除本地的文件。 |
8
xiangyuecn 2021-06-01 17:29:13 +08:00
确实是一个分布式事务 另外:这些功能基本不需要扯上 tcp 吧,顶多发个请求收个响应,不需要骑个自行车还要自己修条马路😂
|
9
xieqiqiang00 2021-06-01 23:01:25 +08:00
想到了那个 TCP 笑话:
我给你发送了一张图片。 我收到了一张图片并且已经保存了。 好的,我要在我这里删除这张图片。 好的,你可以删除这张图片。 我删除了这张图片。 我知道了删除了这张图片。 抱歉!你的连接超时了。我给你发送了...哦不,图片不存在。 |
10
jedihy 2021-06-02 09:46:31 +08:00
跟 tcp 没关系。服务器应用层可以一直重试直到收到客户端的确认。
|
11
julyclyde 2021-06-02 10:56:35 +08:00
你这事其实都不需要可靠性
弱一致性甚至不一致都没啥损害 |