|
|
|
using Elight.Entity;
|
|
|
|
using Elight.Logic;
|
|
|
|
using Elight.Utility;
|
|
|
|
using Elight.Utility.Code;
|
|
|
|
using javax.xml.crypto;
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
using SqlSugar;
|
|
|
|
using System.Data;
|
|
|
|
using System.Net.WebSockets;
|
|
|
|
using System.Runtime.Serialization;
|
|
|
|
using System.Text;
|
|
|
|
using static com.sun.tools.@internal.xjc.reader.xmlschema.bindinfo.BIConversion;
|
|
|
|
using User = Elight.Utility.User;
|
|
|
|
|
|
|
|
namespace _24Hour.Controllers.Common
|
|
|
|
{
|
|
|
|
[Authorize]
|
|
|
|
[ApiController]
|
|
|
|
public class WebSocketController : Controller
|
|
|
|
{
|
|
|
|
private readonly SqlSugarClient _db;//数据库
|
|
|
|
App_Sys_UserModel _userdata = new App_Sys_UserModel();//当前用户
|
|
|
|
private readonly ILogger<LoginController> _logger;//日志
|
|
|
|
private readonly IConfiguration _configuration;
|
|
|
|
Result result = new Result();
|
|
|
|
private static Dictionary<string, WebSocket> CONNECT_POOL = new Dictionary<string, WebSocket>();//用户连接池
|
|
|
|
//private static Dictionary<string, List<MessageInfo>> MESSAGE_POOL = new Dictionary<string, List<MessageInfo>>();//离线消息池
|
|
|
|
public WebSocketController(ILogger<LoginController> logger, SqlSugarClient db,User userdata,IConfiguration configuration)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_db = db;
|
|
|
|
_userdata = userdata.Userdata();
|
|
|
|
_configuration = configuration;
|
|
|
|
}
|
|
|
|
[HttpGet("/ws")]
|
|
|
|
public async Task WebSocketServer()
|
|
|
|
{
|
|
|
|
if (HttpContext.WebSockets.IsWebSocketRequest)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var socket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
|
|
|
await ProcessChat(socket);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private async Task ProcessChat(WebSocket socket)
|
|
|
|
{
|
|
|
|
string user = _userdata.Id;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
#region 用户添加连接池
|
|
|
|
//第一次open时,添加到连接池中
|
|
|
|
if (!CONNECT_POOL.ContainsKey(user))
|
|
|
|
CONNECT_POOL.Add(user, socket);//不存在,添加
|
|
|
|
else
|
|
|
|
if (socket != CONNECT_POOL[user])//当前对象不一致,更新
|
|
|
|
CONNECT_POOL[user] = socket;
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
string descUser = string.Empty;//目的用户
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (socket.State == WebSocketState.Open)
|
|
|
|
{
|
|
|
|
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
|
|
|
|
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
|
|
|
|
if (result.MessageType == WebSocketMessageType.Close)
|
|
|
|
{
|
|
|
|
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var data = Encoding.UTF8.GetString(buffer);
|
|
|
|
Console.WriteLine(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Console.WriteLine("断开连接");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}//while end
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
//整体异常处理
|
|
|
|
if (CONNECT_POOL.ContainsKey(user)) CONNECT_POOL.Remove(user);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 消息发送
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="Sendingdata"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
[HttpPost]
|
|
|
|
[Route("WebSocketSend")]
|
|
|
|
public async Task WebSocketSend(WebSocketSending Sendingdata)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
//获取发送人连接
|
|
|
|
var socket = CONNECT_POOL.Where(q => q.Key == _userdata.Id).Select(q => q.Value).First();
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (socket.State == WebSocketState.Open)
|
|
|
|
{
|
|
|
|
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
|
|
|
|
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
|
|
|
|
|
|
|
|
#region 消息处理(消息转发)
|
|
|
|
try
|
|
|
|
{
|
|
|
|
#region 关闭Socket处理,删除连接池
|
|
|
|
if (socket.State != WebSocketState.Open)//连接关闭
|
|
|
|
{
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);//删除连接池
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 消息发送
|
|
|
|
var content = JsonConvert.SerializeObject(Sendingdata);
|
|
|
|
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
|
|
|
|
|
|
|
|
if (CONNECT_POOL.ContainsKey(Sendingdata.recipient))//判断客户端是否在线
|
|
|
|
{
|
|
|
|
WebSocket destSocket = CONNECT_POOL[Sendingdata.recipient];//目的客户端
|
|
|
|
if (destSocket != null && destSocket.State == WebSocketState.Open)
|
|
|
|
await destSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//添加未读
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//添加未读
|
|
|
|
//添加一条未读消息
|
|
|
|
//Task.Run(() =>
|
|
|
|
//{
|
|
|
|
// if (!MESSAGE_POOL.ContainsKey(descUser))//将用户添加至离线消息池中
|
|
|
|
// MESSAGE_POOL.Add(descUser, new List<MessageInfo>());
|
|
|
|
// MESSAGE_POOL[descUser].Add(new MessageInfo(DateTime.Now, buffer));//添加离线消息
|
|
|
|
//});
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
catch (Exception exs)
|
|
|
|
{
|
|
|
|
//消息转发异常处理,本次消息忽略 继续监听接下来的消息
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}//while end
|
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
|
|
|
//整体异常处理
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 消息发送
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="Sendingdata"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
[HttpPost]
|
|
|
|
[Route("text")]
|
|
|
|
public async Task<Result> text()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
//获取发送人连接
|
|
|
|
var socket = CONNECT_POOL.Where(q => q.Key == _userdata.Id).Select(q => q.Value).First();
|
|
|
|
if (socket.State == WebSocketState.Open)
|
|
|
|
{
|
|
|
|
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
|
|
|
|
//WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
|
|
|
|
|
|
|
|
#region 消息处理(消息转发)
|
|
|
|
try
|
|
|
|
{
|
|
|
|
#region 关闭Socket处理,删除连接池
|
|
|
|
if (socket.State != WebSocketState.Open)//连接关闭
|
|
|
|
{
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);//删除连接池
|
|
|
|
result.IsSucceed = true;
|
|
|
|
result.result = "";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 消息发送
|
|
|
|
var content = "测试test";
|
|
|
|
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
|
|
|
|
await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
catch (Exception exs)
|
|
|
|
{
|
|
|
|
//消息转发异常处理,本次消息忽略 继续监听接下来的消息
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
|
|
|
//整体异常处理
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);
|
|
|
|
}
|
|
|
|
result.IsSucceed = true;
|
|
|
|
result.result = "";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 视频推送
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="Sendingdata"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
[HttpPost]
|
|
|
|
[Route("Video")]
|
|
|
|
public async Task<Result> Video(WebSocketSending Senddata)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
//获取发送人连接
|
|
|
|
var socket = CONNECT_POOL.Where(q => q.Key == _userdata.Id).Select(q => q.Value).FirstOrDefault();
|
|
|
|
if (socket!=null&&socket.State == WebSocketState.Open)
|
|
|
|
{
|
|
|
|
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
|
|
|
|
//WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);
|
|
|
|
|
|
|
|
#region 消息处理(消息转发)
|
|
|
|
try
|
|
|
|
{
|
|
|
|
#region 关闭Socket处理,删除连接池
|
|
|
|
if (socket.State != WebSocketState.Open)//连接关闭
|
|
|
|
{
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);//删除连接池
|
|
|
|
result.IsSucceed = true;
|
|
|
|
result.result = "未上线";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region 消息发送
|
|
|
|
var content = "";
|
|
|
|
//data.type等于1 为视频推送
|
|
|
|
if (Senddata.typenum == "1" && Senddata.deviceno != "")
|
|
|
|
{
|
|
|
|
//设备发送给app
|
|
|
|
//查询远程会见记录
|
|
|
|
var Devicedata = await _db.Queryable<App_DeviceModel>().Where(q => q.deviceno == Senddata.deviceno).ToListAsync();
|
|
|
|
Senddata.content = $"{_configuration.GetSection("Videoaddress:rtsp").Value}{Devicedata.FirstOrDefault()?.deviceno}";
|
|
|
|
//对象序列化
|
|
|
|
content = JsonConvert.SerializeObject(Senddata);
|
|
|
|
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//app发送给设备
|
|
|
|
Senddata.content = $"{_configuration.GetSection("Videoaddress:rtmp").Value}{_userdata.Id}";
|
|
|
|
//对象序列化
|
|
|
|
content = JsonConvert.SerializeObject(Senddata);
|
|
|
|
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(content));
|
|
|
|
}
|
|
|
|
//判断客户端是否在线
|
|
|
|
if (CONNECT_POOL.ContainsKey(Senddata.recipient))
|
|
|
|
{
|
|
|
|
//获取目的客户端
|
|
|
|
WebSocket destSocket = CONNECT_POOL[Senddata.recipient];
|
|
|
|
//判断客户端是否连接
|
|
|
|
if (destSocket != null && destSocket.State == WebSocketState.Open)
|
|
|
|
await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.IsSucceed = false;
|
|
|
|
result.result = "用户未上线";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.IsSucceed = false;
|
|
|
|
result.result = "用户未上线";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
catch (Exception exs)
|
|
|
|
{
|
|
|
|
//消息转发异常处理,本次消息忽略 继续监听接下来的消息
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception)
|
|
|
|
{
|
|
|
|
//整体异常处理
|
|
|
|
if (CONNECT_POOL.ContainsKey(_userdata.Id)) CONNECT_POOL.Remove(_userdata.Id);
|
|
|
|
}
|
|
|
|
result.IsSucceed = true;
|
|
|
|
result.result = "";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 消息发送
|
|
|
|
/// </summary>
|
|
|
|
public class WebSocketSending
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// 发送人
|
|
|
|
/// </summary>
|
|
|
|
[DataMember]
|
|
|
|
public string? sender { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// 发送内容
|
|
|
|
/// </summary>
|
|
|
|
[DataMember]
|
|
|
|
public string? content { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// 接收人
|
|
|
|
/// </summary>
|
|
|
|
[DataMember]
|
|
|
|
public string? recipient { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// 类型 0:消息,1:视频地址
|
|
|
|
/// </summary>
|
|
|
|
[DataMember]
|
|
|
|
public string? typenum { get; set; }
|
|
|
|
/// <summary>
|
|
|
|
/// 设备编号
|
|
|
|
/// </summary>
|
|
|
|
[DataMember]
|
|
|
|
public string? deviceno { get; set; }
|
|
|
|
}
|
|
|
|
}
|