1
- using System ;
1
+ using System ;
2
2
using System . IO ;
3
3
using System . Net . WebSockets ;
4
4
using System . Threading ;
12
12
13
13
using UnityEngine ;
14
14
15
- namespace UnityWebSockets
15
+ namespace NativeWebSocket
16
16
{
17
17
public delegate void WebSocketOpenEventHandler ( ) ;
18
18
public delegate void WebSocketMessageEventHandler ( byte [ ] data ) ;
@@ -136,6 +136,9 @@ public class WebSocket : IWebSocket
136
136
[ DllImport ( "__Internal" ) ]
137
137
public static extern int WebSocketSend ( int instanceId , byte [ ] dataPtr , int dataLength ) ;
138
138
139
+ [ DllImport ( "__Internal" ) ]
140
+ public static extern int WebSocketSendText ( int instanceId , string message ) ;
141
+
139
142
[ DllImport ( "__Internal" ) ]
140
143
public static extern int WebSocketGetState ( int instanceId ) ;
141
144
@@ -148,9 +151,9 @@ public class WebSocket : IWebSocket
148
151
149
152
public WebSocket ( string url )
150
153
{
151
- if ( ! WebSocketFactory . isInitialized ) {
152
- WebSocketFactory . Initialize ( ) ;
153
- }
154
+ if ( ! WebSocketFactory . isInitialized ) {
155
+ WebSocketFactory . Initialize ( ) ;
156
+ }
154
157
155
158
int instanceId = WebSocketFactory . WebSocketAllocate ( url ) ;
156
159
WebSocketFactory . instances . Add ( instanceId , this ) ;
@@ -168,29 +171,44 @@ public int GetInstanceId()
168
171
return this . instanceId ;
169
172
}
170
173
171
- public async Task Connect ( )
174
+ public Task Connect ( )
172
175
{
173
176
int ret = WebSocketConnect ( this . instanceId ) ;
174
177
175
178
if ( ret < 0 )
176
179
throw WebSocketHelpers . GetErrorMessageFromCode ( ret , null ) ;
180
+
181
+ return Task . CompletedTask ;
177
182
}
178
183
179
- public async Task Close ( WebSocketCloseCode code = WebSocketCloseCode . Normal , string reason = null )
184
+ public Task Close ( WebSocketCloseCode code = WebSocketCloseCode . Normal , string reason = null )
180
185
{
181
186
int ret = WebSocketClose ( this . instanceId , ( int ) code , reason ) ;
182
187
183
188
if ( ret < 0 )
184
189
throw WebSocketHelpers . GetErrorMessageFromCode ( ret , null ) ;
190
+
191
+ return Task . CompletedTask ;
185
192
}
186
193
187
- public async Task Send ( byte [ ] data )
194
+ public Task Send ( byte [ ] data )
188
195
{
189
196
int ret = WebSocketSend ( this . instanceId , data , data . Length ) ;
190
197
191
198
if ( ret < 0 )
192
199
throw WebSocketHelpers . GetErrorMessageFromCode ( ret , null ) ;
193
200
201
+ return Task . CompletedTask ;
202
+ }
203
+
204
+ public Task SendText ( string message )
205
+ {
206
+ int ret = WebSocketSendText ( this . instanceId , message ) ;
207
+
208
+ if ( ret < 0 )
209
+ throw WebSocketHelpers . GetErrorMessageFromCode ( ret , null ) ;
210
+
211
+ return Task . CompletedTask ;
194
212
}
195
213
196
214
public WebSocketState State {
@@ -245,7 +263,7 @@ public void DelegateOnCloseEvent(int closeCode)
245
263
246
264
#else
247
265
248
- public class WebSocket : IWebSocket
266
+ public class WebSocket : IWebSocket
249
267
{
250
268
public event WebSocketOpenEventHandler OnOpen ;
251
269
public event WebSocketMessageEventHandler OnMessage ;
@@ -255,7 +273,13 @@ public class WebSocket : IWebSocket
255
273
private Uri uri ;
256
274
private ClientWebSocket m_Socket = new ClientWebSocket ( ) ;
257
275
258
- public WebSocket ( string url )
276
+ private readonly object Lock = new object ( ) ;
277
+
278
+ private bool isSending = false ;
279
+ private List < ArraySegment < byte > > sendBytesQueue = new List < ArraySegment < byte > > ( ) ;
280
+ private List < ArraySegment < byte > > sendTextQueue = new List < ArraySegment < byte > > ( ) ;
281
+
282
+ public WebSocket ( string url )
259
283
{
260
284
uri = new Uri ( url ) ;
261
285
@@ -307,21 +331,108 @@ public WebSocketState State
307
331
}
308
332
}
309
333
310
- public async Task Send ( byte [ ] bytes )
334
+ public Task Send ( byte [ ] bytes )
311
335
{
312
- var buffer = new ArraySegment < byte > ( bytes ) ;
313
- await m_Socket . SendAsync ( buffer , WebSocketMessageType . Binary , true , CancellationToken . None ) ;
336
+ // return m_Socket.SendAsync(buffer, WebSocketMessageType.Binary, true, CancellationToken.None );
337
+ return SendMessage ( sendBytesQueue , WebSocketMessageType . Binary , new ArraySegment < byte > ( bytes ) ) ;
314
338
}
315
339
316
- public async Task SendText ( string message )
340
+ public Task SendText ( string message )
317
341
{
318
342
var encoded = Encoding . UTF8 . GetBytes ( message ) ;
319
- var buffer = new ArraySegment < byte > ( encoded , 0 , encoded . Length ) ;
320
343
321
- await m_Socket . SendAsync ( buffer , WebSocketMessageType . Text , true , CancellationToken . None ) ;
322
- }
344
+ // m_Socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
345
+ return SendMessage ( sendTextQueue , WebSocketMessageType . Text , new ArraySegment < byte > ( encoded , 0 , encoded . Length ) ) ;
346
+ }
347
+
348
+ private async Task SendMessage ( List < ArraySegment < byte > > queue , WebSocketMessageType messageType , ArraySegment < byte > buffer )
349
+ {
350
+ // Return control to the calling method immediately.
351
+ await Task . Yield ( ) ;
352
+
353
+ // Make sure we have data.
354
+ if ( buffer . Count == 0 )
355
+ {
356
+ return ;
357
+ }
358
+
359
+ // The state of the connection is contained in the context Items dictionary.
360
+ bool sending ;
361
+
362
+ lock ( Lock )
363
+ {
364
+ sending = isSending ;
365
+
366
+ // If not, we are now.
367
+ if ( ! isSending )
368
+ {
369
+ isSending = true ;
370
+ }
371
+ }
323
372
324
- public async Task Receive ( )
373
+ if ( ! sending )
374
+ {
375
+ // Lock with a timeout, just in case.
376
+ if ( ! Monitor . TryEnter ( m_Socket , 1000 ) )
377
+ {
378
+ // If we couldn't obtain exclusive access to the socket in one second, something is wrong.
379
+ await m_Socket . CloseAsync ( WebSocketCloseStatus . InternalServerError , string . Empty , CancellationToken . None ) ;
380
+ return ;
381
+ }
382
+
383
+ try
384
+ {
385
+ // Send the message synchronously.
386
+ var t = m_Socket . SendAsync ( buffer , messageType , true , CancellationToken . None ) ;
387
+ t . Wait ( ) ;
388
+ }
389
+ finally
390
+ {
391
+ Monitor . Exit ( m_Socket ) ;
392
+ }
393
+
394
+ // Note that we've finished sending.
395
+ lock ( Lock )
396
+ {
397
+ isSending = false ;
398
+ }
399
+
400
+ // Handle any queued messages.
401
+ await HandleQueue ( queue , messageType ) ;
402
+ }
403
+ else
404
+ {
405
+ // Add the message to the queue.
406
+ lock ( Lock )
407
+ {
408
+ queue . Add ( buffer ) ;
409
+ }
410
+ }
411
+ }
412
+
413
+ private async Task HandleQueue ( List < ArraySegment < byte > > queue , WebSocketMessageType messageType )
414
+ {
415
+ var buffer = new ArraySegment < byte > ( ) ;
416
+ lock ( Lock )
417
+ {
418
+ // Check for an item in the queue.
419
+ if ( queue . Count > 0 )
420
+ {
421
+ // Pull it off the top.
422
+ buffer = queue [ 0 ] ;
423
+ queue . RemoveAt ( 0 ) ;
424
+ }
425
+ }
426
+
427
+ // Send that message.
428
+ if ( buffer . Count > 0 )
429
+ {
430
+ await SendMessage ( queue , messageType , buffer ) ;
431
+ }
432
+ }
433
+
434
+
435
+ public async Task Receive ( )
325
436
{
326
437
ArraySegment < byte > buffer = new ArraySegment < byte > ( new byte [ 8192 ] ) ;
327
438
@@ -377,7 +488,7 @@ public async Task Close()
377
488
378
489
///
379
490
/// Factory
380
- ///
491
+ ///
381
492
382
493
383
494
/// <summary>
@@ -518,4 +629,4 @@ public static WebSocket CreateInstance(string url)
518
629
}
519
630
520
631
521
- }
632
+ }
0 commit comments