240 lines
8.6 KiB
C#
240 lines
8.6 KiB
C#
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());
|
||
});
|
||
}
|
||
}
|
||
}
|