# 问题的引出
云却 12:27:37
@蓝色幻想 如果远程网络主动断开连接，本地已经收到的缓存区里的消息怎么办，应该直接丢弃还是继续处理，因为是异步的的，OnDisconnet函数可能已经执行了，在处理消息是不是不合适

蓝色幻想 12:28:40
直接丢了吧

云却 12:28:43
业务逻辑层正常思维是不是断开连接后，就会认为不会在拿到消息

蓝色幻想 12:28:48
都断线了

牛头人大法师 12:29:01
啊？

牛头人大法师 12:29:06
不是自动重连吗

牛头人大法师 12:29:23
重连能连上，之前的数据不就能用上了？

蓝色幻想 12:29:31
重连之前没收完的也用不了啊

云却 12:29:33
自动重连是自动重来的逻辑，有时候丢了就是丢了

云却 12:30:05
蓝色幻想  
重连之前没收完的也用不了啊
 @蓝色幻想 已经收到的完整包但是还没来得及发到业务层的呢

蓝色幻想 12:30:33
也没啥用吧

云却 12:30:53
发送缓存区没有发送成功的 ，可以在重连后继续发送

蓝色幻想 12:31:09
一瞬间的事情，多看一帧正确画面没啥意义吧

云却 12:31:24
OK，先这样色剂

牛头人大法师 12:31:38
我也觉得丢弃合理一点

蓝色幻想 12:31:48
建议重连不要用之前的东西了

蓝色幻想 12:32:07
该发的状态都发一编就好了

牛头人大法师 12:32:20
disconnect事件都触发了，后面还能收到消息，就和拔了电源，电视还能亮一样

牛头人大法师 12:32:25
有点阴间感觉

云却 12:33:07
……也不对，如果一个用例是， 发送了最后一条消息，然后就断开连接，  对面收到消息防止缓存区力，然后进入断线逻辑，最后一条消息岂不是会被丢弃

牛头人大法师 12:33:20
话说网络层，disconnect这个socket对象都不会再用了吧？

云却 12:33:32
发送端觉得我发了该法的，就断开连接没什么问题怎么办

蓝色幻想 12:33:45
你这是发送方的问题吧

蓝色幻想 12:33:57
我以为你说接收方断开链接

蓝色幻想 12:34:18
发送方我一般的做法是，调close，不是立马close，而是不接受新的发送请求

蓝色幻想 12:34:28
然后等发完了再断开连接

牛头人大法师 12:34:30
不确认就断开的吗
？

云却 12:36:00
A 告诉 B，你自由了，我再也不管你了，就断开了，也是正常思维啊，B发现断开了，但是自由了的消息因为异步存在缓冲区里，等到要处理时发现早已处理完断开连接的业务

牛头人大法师 12:36:20
那有个问题啊

牛头人大法师 12:36:22
丢包了怎么办

牛头人大法师 12:36:31
不确认的话

牛头人大法师 12:36:38
b还是收不到

云却 12:38:33
先确认正常人思维是不是要保证这两点 1：发送端发送最后一条消息，如果觉得不在有业务往来，可以主动断开连接 。 2. 接收端如果处理完远程断开连接逻辑，默认认为不会在得到远程的业务消息。

云却 12:39:46
Freezer  
丢包了怎么办
 @Freezer 当前默认以发送成功，确认是下层保证的

牛头人大法师 12:41:32
下层能确认，是不是会有顺序

牛头人大法师 12:41:43
应该断开在消息之后

牛头人大法师 12:42:00
不知道断开是不是也算一个消息

蓝色幻想 12:42:07
不不

云却 12:42:10
断开不算一个业务消息

蓝色幻想 12:42:16
断开连接，本身也是个消息= =

蓝色幻想 12:42:21
tcp而言的话

云却 12:42:22
！

蓝色幻想 12:42:34
除非你直接拔网线

蓝色幻想 12:42:38
物理切断

牛头人大法师 12:42:54
那tcp不是有顺序吗

蓝色幻想 12:42:59
是的

牛头人大法师 12:43:10
那应该不会出现断开在消息之前吧

蓝色幻想 12:43:11
所以只要你把缓存里的发完了再断开连接

蓝色幻想 12:43:12
就行了

蓝色幻想 12:43:30
udp什么的就不一定了

蓝色幻想 12:43:39
udp本身就没有链接这回事

云却 12:43:41
Freezer  
那tcp不是有顺序吗
 @Freezer tcp有序，但是网络层为了高效会大量使用异步，所以要重新保证有序

云却 12:43:58
蓝色幻想  
所以只要你把缓存里的发完了再断开连接
 @蓝色幻想 嗯，基本理清了

蓝色幻想 12:44:48
tcp 断开链接要有4个消息

蓝色幻想 12:45:20
->FIN
<- FIN + ACK
->ACK

蓝色幻想 12:45:25
然后才会断线

云却 12:45:49
我先整理成文档，如果到晚上还没有想到其他极端案例，就按照这个思路实施

# 明确需求
正常人思维要保证
1. 发送端发送最后一条消息，如果觉得不在有业务往来，可以主动断开连接。
2. 发送端主动调用断开函数，要保证已经调用发送函数的消息可以发送。
3. 接收端如果处理完远程断开连接逻辑，默认认为不会再得到远程的业务消息。

# 具体设计
1. 发送端手动调用断开，等待发送缓冲区发送完毕后断开，不在允许新的发送，并立刻停止接收，直接舍弃接收缓冲区消息。
2. 接收端发现断开，立刻停止发送，保留发送缓冲区留给重连备用，允许新发送直到断开逻辑执行完毕，保存在发送缓冲区。（发出断开警告信号，给断线重连机制使用） 等待已接收完整的消息处理完毕，执行断开逻辑。

# 处理4中情况
1. 发送时错误
2. 接收时错误
3. 接收0字节
4. 主动断开


# 参考
- Socket.Shutdown(SocketShutdown.Send);调用后，远端接收函数会一直收到0字节，同步函数不会阻塞，异步函数同步完成。
