Waste/WasteConsoleTest/WasteConsoleTest/WSocketClientHelp.cs

240 lines
8.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WasteConsoleTest
{
public class WSocketClientHelp
{
ClientWebSocket ws = null;
Uri uri = null;
bool isUserClose = false;//是否最后由用户手动关闭
public static string Secret = "lsBThmYBYUMrmwkl";
public static string SecretHash = "bfbaf98fb5b343b2";
public static string deviceid = "08d9588d-4796-48f9-8c5b-f28f271b51d0";
// <summary>
/// WebSocket状态
/// </summary>
public WebSocketState? State { get => ws?.State; }
/// <summary>
/// 包含一个数据的事件
/// </summary>
public delegate void MessageEventHandler(object sender, string data);
public delegate void ErrorEventHandler(object sender, Exception ex);
/// <summary>
/// 连接建立时触发
/// </summary>
public event EventHandler OnOpen;
/// <summary>
/// 客户端接收服务端数据时触发
/// </summary>
public event MessageEventHandler OnMessage;
/// <summary>
/// 通信发生错误时触发
/// </summary>
public event ErrorEventHandler OnError;
/// <summary>
/// 连接关闭时触发
/// </summary>
public event EventHandler OnClose;
public WSocketClientHelp(string wsUrl)
{
uri = new Uri(wsUrl);
ws = new ClientWebSocket();
}
/// <summary>
/// 打开链接
/// </summary>
public void Open()
{
Task.Run(async () =>
{
if (ws.State == WebSocketState.Connecting || ws.State == WebSocketState.Open)
return;
string netErr = string.Empty;
try
{
//初始化链接
isUserClose = false;
ws = new ClientWebSocket();
// ws.Options.AddSubProtocol("protocol1"); //使用的协议
ws.Options.SetRequestHeader("device", deviceid); //设备ID
ws.Options.SetRequestHeader("secret", SecretHash); //设备secrethash
ws.Options.SetRequestHeader("time", GetTimestamp().ToString()); //时间戳
ws.Options.SetRequestHeader("os", "12"); //操作系统Android ArmV7
ws.Options.SetRequestHeader("script", "2"); //设备支持的脚本语言运行环境,1-lua5.4 2-javascript
ws.Options.SetRequestHeader("baseProgrameLang", "10"); //宿主程序语言,java
ws.Options.SetRequestHeader("dev", "true");//开发环境,bool类型
await ws.ConnectAsync(uri, CancellationToken.None); //建立连接
if (OnOpen != null)
OnOpen(ws, new EventArgs());
Send(@"{""protocol"":""json"", ""version"":1}");//建立之后第一步进行握手使用json类型
//全部消息容器
List<byte> bs = new List<byte>();
//缓冲区
var buffer = new byte[1024 * 4];
//监听Socket信息
WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
//是否关闭
while (!result.CloseStatus.HasValue)
{
//文本消息
if (result.MessageType == WebSocketMessageType.Text)
{
bs.AddRange(buffer.Take(result.Count));
//消息是否已接收完全
if (result.EndOfMessage)
{
var arr = RemoveSeparator(bs.ToArray());//过滤掉记录分隔符
//发送过来的消息
string userMsg = Encoding.UTF8.GetString(arr, 0, arr.Length);
if (OnMessage != null)
OnMessage(ws, userMsg);
//清空消息容器
bs = new List<byte>();
}
}
//继续监听Socket信息
result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
////关闭WebSocket服务端发起
//await ws.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
catch (Exception ex)
{
netErr = "发生错误" + ex.Message;
if (OnError != null)
OnError(ws, ex);
//if (ws != null && ws.State == WebSocketState.Open)
// //关闭WebSocket客户端发起
// await ws.CloseAsync(WebSocketCloseStatus.Empty, ex.Message, CancellationToken.None);
}
finally
{
if (!isUserClose)
Close(ws.CloseStatus.Value, ws.CloseStatusDescription + netErr);
}
});
}
/// <summary>
/// 增加记录分隔符
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private static byte[] AddSeparator(byte[] data)
{
List<byte> t = new List<byte>(data) { 0x1e };//0x1e record separator
return t.ToArray();
}
//删除记录分隔符
private static byte[] RemoveSeparator(byte[] data)
{
List<byte> t = new List<byte>(data);
t.Remove(0x1e);
return t.ToArray();
}
/// <summary>
/// 获取时间戳
/// </summary>
/// <returns></returns>
private int GetTimestamp()
{
DateTime dateTimeStart = TimeZoneInfo.ConvertTimeToUtc(new DateTime(1970, 1, 1, 8, 0, 0));
int timestamp = Convert.ToInt32((DateTime.Now - dateTimeStart).TotalSeconds);
return timestamp;
}
/// <summary>
/// 使用连接发送文本消息
/// </summary>
/// <param name="ws"></param>
/// <param name="mess"></param>
/// <returns>是否尝试了发送</returns>
public bool Send(string mess)
{
if (ws.State != WebSocketState.Open)
return false;
Task.Run(async () =>
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")},发送数据:{mess}");
var replyMess = Encoding.UTF8.GetBytes(mess);
//发送消息,结尾必须携带记录分隔符
await ws.SendAsync(new ArraySegment<byte>(AddSeparator(replyMess)), WebSocketMessageType.Text, true, CancellationToken.None);
});
return true;
}
/// <summary>
/// 使用连接发送字节消息
/// </summary>
/// <param name="ws"></param>
/// <param name="mess"></param>
/// <returns>是否尝试了发送</returns>
public bool Send(byte[] bytes)
{
if (ws.State != WebSocketState.Open)
return false;
Task.Run(async () =>
{
//发送消息
await ws.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Binary, true, CancellationToken.None);
});
return true;
}
/// <summary>
/// 关闭连接
/// </summary>
public void Close()
{
isUserClose = true;
Close(WebSocketCloseStatus.NormalClosure, "用户手动关闭");
}
public void Close(WebSocketCloseStatus closeStatus, string statusDescription)
{
Task.Run(async () =>
{
try
{
//关闭WebSocket客户端发起
await ws.CloseAsync(closeStatus, statusDescription, CancellationToken.None);
}
catch (Exception ex)
{
}
ws.Abort();
ws.Dispose();
if (OnClose != null)
OnClose(ws, new EventArgs());
});
}
}
}