本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程。本产品已经成熟稳定并投入商用。

在线演示环境:https://kf.shengxunwei.com 注意:演示环境仅供演示交流与评估,不保证 7x24 小时可用。

文章目录列表请点击这里


演示网络中断,直接禁用网卡,或者手机进入飞行模式,也不丢消息,不出异常。

视频地址:https://v.youku.com/v_show/id_XNTEwNzQ5Mzg2OA==.html


TCP 报文的确认机制

首先我们回顾一下 TCP 协议,TCP 报文格式一般如下所示:

其中的 ACK ,表示对报文是否送达的一个回应。



ACK是TCP标头中的标志和字段。 发送一个消息至少需要一个标头,再加上所有较低层的内容。

下图则显示了 TCP 通信时,客户端和服务端之间报文传送的过程。

从图中可以看到,发出的消息,和回应的消息,都会有一个编号,如:#1、#2

在ACK报文回应时,它回附带上所收到的报文的编号,那么发送端只需根据收到的ACK报文中的编号,就能判定报文是否送达,已经所送达的数据包。如果在一定时间内,没有收到回应的ACK消息,则发送端会在一定时间内重新尝试发送。

通过 C# 实现拔网线也不丢消息的高可靠通信

基于 TCP 协议自有的消息确认机制,我们在上层应用中实现可靠的通信就比较简单了。底层通信相关的类已经帮我们实现好了可靠的 TCP 传输,一旦出现网络异常,我们在上层都能够收到相应的通知。

客户端自身网络异常

这种情况最好处理。因为客户端程序异常退出会直接引发 ConnectionReset 的 Socket 异常。我们只需要在服务端捕获这个异常进行处理即可:

 public bool Send(byte[] data)
{
// 连接已经断开了
try
{
_networkStream.Write(data, 0, data.Length);
}
catch (Exception ex)
{
OnDisconnected(ex);
return false;
} return true;
}

网络链路异常

对于这种情况,我们只需要检测 Socket 对象的 Connected 属性。

但是需要特别注意:Socket 对象的 Connected 属性获取从 Socket 最后一个 i/o 操作到的的连接状态。 当它返回时 false , Socket 要么从未连接,要么不再处于连接状态。当 Socket 从另一个线程断开连接时,它可能会在操作中止后返回。

如果需要确定连接的当前状态,请发出非阻止的零字节发送调用。 如果调用成功返回或引发 WAEWOULDBLOCK 错误代码 (10035) ,则套接字仍处于连接状态;否则,将不再连接套接字。

我们可以通过实现一个定时心跳,来对网络链路进行检测:

_heartbeatTimer = new Timer((state) =>
{
HeartbeatMessage heartbeatMessage = new HeartbeatMessage();
Send(heartbeatMessage); }, null, 3000, 3000);

在定时器发送心跳时,如果网络链路中断,我们可以收到以下消息:

 private void _socketClient_Disconnected(object sender, EventArgs e)
{
if (_heartbeatTimer != null)
_heartbeatTimer.Dispose(); if (_socketClient != null)
{
_socketClient.Close();
_socketClient = null;
}
}

只需针对 Disconnected 事件,进行处理,将两端的状态,置于等待即可。


在线演示环境:https://kf.shengxunwei.com 注意:演示环境仅供演示交流与评估,不保证 7x24 小时可用。

联系QQ: 279060597

联系E-mail:C5118@outlook.com

最新文章

  1. 写Python脚本语言时,“SyntaxError: Non-ASCII character '\xe6' in file”错误的处理
  2. C# RSA 分段加解密
  3. HDU2389-Rain on your Parade-二分图匹配-ISAP
  4. VS快速格式化代码
  5. POJ 2823
  6. Linux系统中如何添加自己的库文件路径
  7. 【开源.NET】轻量级内容管理框架Grissom.CMS(第三篇解析配置文件和数据以转换成 sql)
  8. 翻译:JVM虚拟机规范1.7中的运行时常量池部分(一)
  9. LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  10. 记录下curl的使用方法
  11. MT【284】构造函数的导数的两类题型
  12. 前端 ---BOM的介绍
  13. MySQL数据库权限分类
  14. nvidia-docker2配置与NVIDIA驱动安装
  15. python(62):保留两位小数
  16. redis 五种数据类型
  17. Spring的AOP编程
  18. 【转】高效率编辑器VIM
  19. zoj-3329-期望/dp/方程优化
  20. linux安装报错之:ifconfig command not found解决

热门文章

  1. redis学习教程四《管理、备份、客户端连接》
  2. spark SQL(三)数据源 Data Source----通用的数据 加载/保存功能
  3. hive-2.2.0 伪分布式环境搭建
  4. redis防止重复提交
  5. php开发扩展环境的搭建(Windows)
  6. 简述vue-cli 2.x和vue-cli 3+在项目构建、运行、编译执行时的区别
  7. Java线程 - sleep()和wait()方法的区别, 线程阻塞BLOCKED和等待WAITING的区别
  8. Azure Functions(一)什么是 ServerLess
  9. hdu4352 XHXJ's LIS (数位dp)
  10. 2019 ICPC Asia Taipei-Hsinchu Regional Problem J Automatic Control Machine (DFS,bitset)