程序地带

.net core 和 WPF 开发升讯威在线客服与营销系统:使用 WebSocket 实现访客端通信


本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程。本产品已经成熟稳定并投入商用。
在线演示环境:https://kf.shengxunwei.com 注意:演示环境仅供演示交流与评估,不保证 7x24 小时可用。


文章目录列表请点击这里


对于在线客服与营销系统,访客端是指浏览网站的互联网用户,或是通过APP、微信等内嵌聊天页面与后台客服交流的用户,在本篇文章中,我将详细介绍如何在 .net core 环境下使用 WebSocket 技术实现访客在网页上与服务器进行通信。


这里存在几个技术难点需要注意:


聊天界面要能无缝嵌入客户的目标网站,对原网站不能有任何影响。
访客可以通过网站右下角的浮动框,一边聊天一边浏览网站,网页的跳转、刷星都不能中断聊天。
需要考虑手机端聊天页面连接不稳定的情况,要能在APP或浏览器切到手机后台失去连接时,对聊天状态和信息进行保持。

访客端实现的效果:



访客端在手机上的效果:



后台客服的实现效果:



在 asp.net core 中配置中间件

首先我们要在 Startup.cs 中,启用 WebSocket 中间件:


var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
app.UseWebSockets(webSocketOptions);

可配置以下设置:


KeepAliveInterval - 向客户端发送“ping”帧的频率,以确保代理保持连接处于打开状态。 默认值为 2 分钟。
ReceiveBufferSize - 用于接收数据的缓冲区的大小。 高级用户可能需要对其进行更改,以便根据数据大小调整性能。 默认值为 4 KB。
AllowedOrigins - 用于 WebSocket 请求的允许的 Origin 标头值列表。 默认情况下,允许使用所有源。
接收访客端的请求

在请求生命周期后期(例如在 Configure 方法或操作方法的后期),检查它是否是 WebSocket 请求并接受 WebSocket 请求。


app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
await Echo(context, webSocket);
}
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});

在请求期间对 Task 执行 await,如下面的示例所示:


app.Use(async (context, next) =>
{
using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
var socketFinishedTcs = new TaskCompletionSource<object>();
BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);
await socketFinishedTcs.Task;
}
});

如果从操作方法返回过快,则还可能发生 WebSocket 关闭异常。 接受操作方法中的套接字时,需要用该套接字的代码完成运行,然后再从操作方法返回。


收发访客端消息

AcceptWebSocketAsync 方法将 TCP 连接升级到 WebSocket 连接,并提供 WebSocket 对象。 使用 WebSocket 对象发送和接收消息。
之前显示的接受 WebSocket 请求的代码将 WebSocket 对象传递给 Echo 方法。 代码接收消息并立即发回相同的消息。 循环发送和接收消息,直到客户端关闭连接:


private async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}

如果在开始循环之前接受 WebSocket 连接,中间件管道会结束。 关闭套接字后,管道展开。 即接受 WebSocket 时,请求停止在管道中推进。 循环结束且套接字关闭时,请求继续回到管道。


处理访客端连接断开

访客端由于失去连接而断开连接时,不会自动向服务器发送通知。 服务器只有在客户端发送通知时才会收到断开连接消息。
如果客户端并非总是发送消息且不希望仅由于连接进入空闲状态就设置超时,则让客户端使用一个计时器并每隔多少秒发送一条心跳消息。 在服务器上,如果某条消息在上一条消息发出后的多少秒内尚未到达,则终止连接并报告客户端已断开连接。


本文对使用 WebSocket 搭建访客端通信框架进行了简要的介绍,在接下来的文章中,我将具体解构服务端程序的结构和设计、客服端程序的结构和设计,敬请关注。


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


联系QQ: 279060597


推荐您关注我的微信订阅号,在我更新文章或产品信息时会进行推送。


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/sheng_chao/p/14280865.html

随机推荐

nodejs快速连接mongodb,实现数据操作

 文章目录目录前言一、nodejs是什么?二、mongodb是什么?  2.1新增数据    第一种方法:创建集合的形式    第二种:创建文档...

也就会一点点 阅读(714)

kafka 削峰_十分钟入门消息系统Kafka

kafka 削峰_十分钟入门消息系统Kafka

本文将对Kafka做一个入门简介,并展示如何使用Kafka构建一个文本数据流管道。通过本文,读者可以了解一个流处理数据管道(Pipeline)的大致结构:数据...

weixin_39747721 阅读(503)

2021-01-05

前段时间接手一个老项目,迭代开发过程使用fastjson泛型工具时出现了反序列化失败的问题,对此将该问题与大家分享,防止各位使用该工具的同学踩坑,...

已经是奶爸 阅读(257)

算法系列——背包问题总结

写在前面“背包问题”是一个非常经典的问题.状态定义dp[i][j]:表示当使用goods[0,…,i],最多可装j重量物品时,此时背包最多能装物品的价值&#x...

BridgeGeorge 阅读(760)

你的场景真的适合使用分布式锁吗?

你的场景真的适合使用分布式锁吗?

最近面试很多候选人的时候,在以往的工作中都使用过分布式锁,问他使用场景,都是认为并发了,要使用分布式锁控制;接着问:...

一杯Java 阅读(610)