c# 实现ws连接,心跳,断线重连,可以自定义心跳内容,心跳间隔,最大重连次数,uri 代码要有注释
时间: 2023-12-06 21:03:49 浏览: 40
以下是基于C#实现WebSocket连接、心跳、断线重连的代码,包含自定义心跳内容、心跳间隔、最大重连次数和代码注释:
```csharp
using System;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
public class WebSocketClient
{
private ClientWebSocket webSocket;
private CancellationTokenSource cancellationTokenSource;
private int maxRetryCount = 3;
private int currentRetryCount = 0;
// 心跳内容
private string pingMessage = "ping";
// 心跳间隔,单位:毫秒
private int pingInterval = 30000;
public WebSocketClient()
{
webSocket = new ClientWebSocket();
cancellationTokenSource = new CancellationTokenSource();
}
public async Task Connect(string uri)
{
try
{
await webSocket.ConnectAsync(new Uri(uri), cancellationTokenSource.Token);
Console.WriteLine("WebSocket connected.");
StartPing(); // 连接成功后开始心跳
}
catch (Exception ex)
{
Console.WriteLine($"WebSocket connect error: {ex.Message}");
if (currentRetryCount < maxRetryCount) // 重连
{
currentRetryCount++;
Console.WriteLine($"Retry after {currentRetryCount} seconds...");
await Task.Delay(currentRetryCount * 1000);
await Connect(uri);
}
else
{
Console.WriteLine("WebSocket connect failed.");
}
}
}
private async Task Receive()
{
try
{
while (webSocket.State == WebSocketState.Open)
{
var buffer = new byte[1024];
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancellationTokenSource.Token);
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationTokenSource.Token);
}
else
{
var message = System.Text.Encoding.UTF8.GetString(buffer);
Console.WriteLine($"Received message: {message}");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"WebSocket receive error: {ex.Message}");
if (currentRetryCount < maxRetryCount) // 重连
{
currentRetryCount++;
Console.WriteLine($"Retry after {currentRetryCount} seconds...");
await Task.Delay(currentRetryCount * 1000);
await Connect(webSocket.Options.OriginalString);
}
else
{
Console.WriteLine("WebSocket receive failed.");
}
}
}
private async Task Send(string message)
{
try
{
var buffer = System.Text.Encoding.UTF8.GetBytes(message);
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, cancellationTokenSource.Token);
}
catch (Exception ex)
{
Console.WriteLine($"WebSocket send error: {ex.Message}");
if (currentRetryCount < maxRetryCount) // 重连
{
currentRetryCount++;
Console.WriteLine($"Retry after {currentRetryCount} seconds...");
await Task.Delay(currentRetryCount * 1000);
await Connect(webSocket.Options.OriginalString);
}
else
{
Console.WriteLine("WebSocket send failed.");
}
}
}
private async Task StartPing()
{
while (webSocket.State == WebSocketState.Open)
{
try
{
await Send(pingMessage);
await Task.Delay(pingInterval);
}
catch (Exception ex)
{
Console.WriteLine($"WebSocket ping error: {ex.Message}");
if (currentRetryCount < maxRetryCount) // 重连
{
currentRetryCount++;
Console.WriteLine($"Retry after {currentRetryCount} seconds...");
await Task.Delay(currentRetryCount * 1000);
await Connect(webSocket.Options.OriginalString);
}
else
{
Console.WriteLine("WebSocket ping failed.");
}
}
}
}
public async Task Close()
{
cancellationTokenSource.Cancel();
currentRetryCount = 0;
try
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
Console.WriteLine("WebSocket closed.");
}
catch (Exception ex)
{
Console.WriteLine($"WebSocket close error: {ex.Message}");
}
}
}
```
使用方式:
```csharp
WebSocketClient client = new WebSocketClient();
await client.Connect("ws://localhost:8080");
await client.Send("hello world");
await Task.Delay(5000); // 等待5秒
await client.Close();
```