Как правильнее всего сделать переподключение к websocket?
Есть следующий код:
public class WsClient
{
// WebSocket
private ClientWebSocket ws = new ClientWebSocket();
private UTF8Encoding encoder; // For websocket text message encoding.
private const UInt64 MAXREADSIZE = 1 * 1024 * 1024;
// Server address
private Uri serverUri;
// Queues
public ConcurrentQueue<String> receiveQueue { get; }
public BlockingCollection<ArraySegment<byte>> sendQueue { get; }
// Threads
private Thread receiveThread { get; set; }
private Thread sendThread { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="T:WsClient"/> class.
/// </summary>
/// <param name="serverURL">Server URL.</param>
public WsClient(string serverURL)
{
encoder = new UTF8Encoding();
ws = new ClientWebSocket();
serverUri = new Uri(serverURL);
receiveQueue = new ConcurrentQueue<string>();
receiveThread = new Thread(RunReceive);
receiveThread.Start();
sendQueue = new BlockingCollection<ArraySegment<byte>>();
sendThread = new Thread(RunSend);
sendThread.Start();
}
/// <summary>
/// Method which connects client to the server.
/// </summary>
/// <returns>The connect.</returns>
public async Task Connect()
{
Debug.WriteLine("Connecting to: " + serverUri);
await ws.ConnectAsync(serverUri, CancellationToken.None);
while (IsConnecting())
{
Debug.WriteLine("Waiting to connect...");
Task.Delay(50).Wait();
}
Debug.WriteLine("Connect status: " + ws.State);
}
#region [Status]
/// <summary>
/// Return if is connecting to the server.
/// </summary>
/// <returns><c>true</c>, if is connecting to the server, <c>false</c> otherwise.</returns>
public bool IsConnecting()
{
return ws.State == WebSocketState.Connecting;
}
/// <summary>
/// Return if connection with server is open.
/// </summary>
/// <returns><c>true</c>, if connection with server is open, <c>false</c> otherwise.</returns>
public bool IsConnectionOpen()
{
return ws.State == WebSocketState.Open;
}
#endregion
#region [Send]
/// <summary>
/// Method used to send a message to the server.
/// </summary>
/// <param name="message">Message.</param>
public void Send(string message)
{
byte[] buffer = encoder.GetBytes(message);
//Debug.Log("Message to queue for send: " + buffer.Length + ", message: " + message);
var sendBuf = new ArraySegment<byte>(buffer);
sendQueue.Add(sendBuf);
}
/// <summary>
/// Method for other thread, which sends messages to the server.
/// </summary>
private async void RunSend()
{
Debug.WriteLine("WebSocket Message Sender looping.");
ArraySegment<byte> msg;
while (true)
{
while (!sendQueue.IsCompleted)
{
msg = sendQueue.Take();
//Debug.Log("Dequeued this message to send: " + msg);
await ws.SendAsync(msg, WebSocketMessageType.Text, true /* is last part of message */, CancellationToken.None);
}
}
}
#endregion
#region [Receive]
/// <summary>
/// Reads the message from the server.
/// </summary>
/// <returns>The message.</returns>
/// <param name="maxSize">Max size.</param>
private async Task<string> Receive(UInt64 maxSize = MAXREADSIZE)
{
// A read buffer, and a memory stream to stuff unknown number of chunks into:
byte[] buf = new byte[4 * 1024];
var ms = new MemoryStream();
ArraySegment<byte> arrayBuf = new ArraySegment<byte>(buf);
WebSocketReceiveResult chunkResult = null;
if (IsConnectionOpen())
{
do
{
chunkResult = await ws.ReceiveAsync(arrayBuf, CancellationToken.None);
ms.Write(arrayBuf.Array, arrayBuf.Offset, chunkResult.Count);
//Debug.Log("Size of Chunk message: " + chunkResult.Count);
if ((UInt64)(chunkResult.Count) > MAXREADSIZE)
{
Console.Error.WriteLine("Warning: Message is bigger than expected!");
}
} while (!chunkResult.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
// Looking for UTF-8 JSON type messages.
byte[] msgBytes = arrayBuf.Skip(arrayBuf.Offset).Take(chunkResult.Count).ToArray();
return Encoding.UTF8.GetString(msgBytes);
}
return "";
}
/// <summary>
/// Method for other thread, which receives messages from the server.
/// </summary>
private async void RunReceive()
{
Debug.WriteLine("WebSocket Message Receiver looping.");
string result;
while (true)
{
//Debug.Log("Awaiting Receive...");
result = await Receive();
if (result != null && result.Length > 0)
{
receiveQueue.Enqueue(result);
}
else
{
Task.Delay(50).Wait();
}
}
}
#endregion
}
Вебсокет отлично работает, однако когда происходит что-то со связью, или сервер почему-то отвалился, то прием просто останавливается. Пробовал помещать все в try catch, но исключений никаких не возникает. Сейчас думаю проверять интервал времени как долго не приходили сообщения и делать переподключение. Но насколько мне известно если закрыть вебсокет, то заново пользоваться им уже нельзя. Как лучше всего сделать переподключение в данном случае?
Код чтения следующий:
while (true)
{
if (cqueue.TryDequeue(out rcvMsg))
{
//обработка данных
}
}