mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-11-05 22:16:32 +08:00
Refactor the WebSocket channel and remove the internal queue.
This commit is contained in:
@@ -13,6 +13,8 @@ namespace MQTTnet.Client
|
|||||||
|
|
||||||
public CookieContainer CookieContainer { get; set; }
|
public CookieContainer CookieContainer { get; set; }
|
||||||
|
|
||||||
|
public int BufferSize { get; set; } = 4096;
|
||||||
|
|
||||||
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
public MqttClientTlsOptions TlsOptions { get; set; } = new MqttClientTlsOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -13,19 +11,19 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
public sealed class MqttWebSocketChannel : IMqttChannel
|
public sealed class MqttWebSocketChannel : IMqttChannel
|
||||||
{
|
{
|
||||||
// ReSharper disable once MemberCanBePrivate.Global
|
|
||||||
// ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
|
|
||||||
public static int BufferSize { get; set; } = 4096; // Can be changed for fine tuning by library user.
|
|
||||||
|
|
||||||
private readonly byte[] _chunckBuffer = new byte[BufferSize];
|
|
||||||
private readonly Queue<byte> _buffer = new Queue<byte>(BufferSize);
|
|
||||||
private readonly MqttClientWebSocketOptions _options;
|
private readonly MqttClientWebSocketOptions _options;
|
||||||
|
private readonly byte[] _chunkBuffer;
|
||||||
|
|
||||||
|
private int _chunkBufferLength;
|
||||||
|
private int _chunkBufferOffset;
|
||||||
|
|
||||||
private WebSocket _webSocket;
|
private WebSocket _webSocket;
|
||||||
|
|
||||||
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
public MqttWebSocketChannel(MqttClientWebSocketOptions options)
|
||||||
{
|
{
|
||||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||||
|
|
||||||
|
_chunkBuffer = new byte[options.BufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
public MqttWebSocketChannel(WebSocket webSocket)
|
public MqttWebSocketChannel(WebSocket webSocket)
|
||||||
@@ -103,28 +101,18 @@ namespace MQTTnet.Implementations
|
|||||||
{
|
{
|
||||||
var bytesRead = 0;
|
var bytesRead = 0;
|
||||||
|
|
||||||
// Use existing date from buffer.
|
|
||||||
while (count > 0 && _buffer.Any())
|
|
||||||
{
|
|
||||||
buffer[offset] = _buffer.Dequeue();
|
|
||||||
count--;
|
|
||||||
bytesRead++;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch new data if the buffer is not full.
|
|
||||||
while (_webSocket.State == WebSocketState.Open)
|
while (_webSocket.State == WebSocketState.Open)
|
||||||
{
|
{
|
||||||
await FetchChunkAsync(cancellationToken).ConfigureAwait(false);
|
await EnsureFilledChunkBufferAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
if (_chunkBufferLength == 0)
|
||||||
while (count > 0 && _buffer.Any())
|
|
||||||
{
|
{
|
||||||
buffer[offset] = _buffer.Dequeue();
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count > 0 && _chunkBufferOffset < _chunkBufferLength)
|
||||||
|
{
|
||||||
|
buffer[offset] = _chunkBuffer[_chunkBufferOffset];
|
||||||
|
_chunkBufferOffset++;
|
||||||
count--;
|
count--;
|
||||||
bytesRead++;
|
bytesRead++;
|
||||||
offset++;
|
offset++;
|
||||||
@@ -136,11 +124,6 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_webSocket.State == WebSocketState.Closed)
|
|
||||||
{
|
|
||||||
throw new MqttCommunicationException("WebSocket connection closed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,22 +147,29 @@ namespace MQTTnet.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FetchChunkAsync(CancellationToken cancellationToken)
|
private async Task EnsureFilledChunkBufferAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(_chunckBuffer, 0, _chunckBuffer.Length), cancellationToken).ConfigureAwait(false);
|
if (_chunkBufferOffset < _chunkBufferLength)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_webSocket.State == WebSocketState.Closed)
|
||||||
|
{
|
||||||
|
throw new MqttCommunicationException("WebSocket connection closed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = await _webSocket.ReceiveAsync(new ArraySegment<byte>(_chunkBuffer, 0, _chunkBuffer.Length), cancellationToken).ConfigureAwait(false);
|
||||||
|
_chunkBufferLength = response.Count;
|
||||||
|
_chunkBufferOffset = 0;
|
||||||
|
|
||||||
if (response.MessageType == WebSocketMessageType.Close)
|
if (response.MessageType == WebSocketMessageType.Close)
|
||||||
{
|
{
|
||||||
await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
throw new MqttCommunicationException("The WebSocket server closed the connection.");
|
||||||
|
//await _webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else if (response.MessageType == WebSocketMessageType.Binary)
|
|
||||||
{
|
if (response.MessageType == WebSocketMessageType.Text)
|
||||||
for (var i = 0; i < response.Count; i++)
|
|
||||||
{
|
|
||||||
_buffer.Enqueue(_chunckBuffer[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (response.MessageType == WebSocketMessageType.Text)
|
|
||||||
{
|
{
|
||||||
throw new MqttProtocolViolationException("WebSocket channel received TEXT message.");
|
throw new MqttProtocolViolationException("WebSocket channel received TEXT message.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user