-
Notifications
You must be signed in to change notification settings - Fork 0
/
WebSocketClient.cs
154 lines (135 loc) · 4.72 KB
/
WebSocketClient.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
namespace LogicReinc.Asp
{
/// <summary>
/// Baseclass for using WebSocket, descendent object is passed to AddWebSocket or AddWebSocketAuthenticated
/// </summary>
public class WebSocketClient
{
private CancellationTokenSource _cancelToken = new CancellationTokenSource();
private AspServer _server = null;
public HttpContext Context { get; set; }
public WebSocket Socket { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public WebSocketClient(string group, AspServer server, HttpContext req, WebSocket socket)
{
Context = req;
Socket = socket;
Name = group;
_server = server;
}
/// <summary>
/// Main WebSocket loop
/// </summary>
internal async Task Handle()
{
Active = true;
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[4096]);
OnConnected();
while (Active)
{
try
{
byte[] resultBinary = null;
string resultStr = null;
using (MemoryStream str = new MemoryStream())
{
WebSocketMessageType type = WebSocketMessageType.Binary;
WebSocketReceiveResult result = null;
//Retrieve all message parts
do
{
result = await Socket.ReceiveAsync(buffer, _cancelToken.Token);
type = result.MessageType;
str.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
//Construct Message
if (buffer.Count > 0)
{
switch (type)
{
case WebSocketMessageType.Text:
str.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(str))
resultStr = reader.ReadToEnd();
break;
case WebSocketMessageType.Binary:
resultBinary = str.ToArray();
break;
case WebSocketMessageType.Close:
Active = false;
OnDisconnected();
await Socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", _cancelToken.Token);
break;
}
}
}
//Call Handler
Task.Run(() =>
{
if (resultStr != null)
HandleString(resultStr);
else if (resultBinary != null)
HandleBytes(resultBinary);
});
}
catch(Exception ex)
{
OnException(ex);
//Just in case.
Thread.Sleep(5);
}
}
_server.RemoveWebSocketClient(Name, this);
}
/// <summary>
/// Called on connection
/// </summary>
public virtual void OnConnected()
{
}
/// <summary>
/// Called on disconnection
/// </summary>
public virtual void OnDisconnected()
{
}
/// <summary>
/// Called on an exception (in loop)
/// </summary>
/// <param name="ex"></param>
public virtual void OnException(Exception ex)
{
}
/// <summary>
/// Called on receiving a message(string)
/// </summary>
public virtual void HandleString(string msg)
{
}
/// <summary>
/// Called on receiving a message(binary)
/// </summary>
public virtual void HandleBytes(byte[] msg)
{
}
/// <summary>
/// To close socket
/// </summary>
public void Close()
{
Active = false;
_cancelToken.Cancel();
}
}
}