摘要
欧洲市场量化监控系统中,德国 DAX 指数期货是核心观测标的。本文基于 C# ClientWebSocket 实现完整的长连接监听客户端,包含心跳保活、断线自动重连、行情结构化解析,适合.NET 技术栈项目集成,数据源采用脉动行情数据 API。
关键词:C#;WebSocket;德指 DAX;欧洲期货;实时行情
一、业务背景
德指 DAX 期货跟踪德国 DAX30 指数,是欧洲股市的核心风向标。很多.NET 技术栈的量化系统对接长连接行情时,容易踩心跳缺失、断连无重连、同步阻塞等坑。 本文采用异步 WebSocket 实现,全程非阻塞,支持 7×24 小时稳定运行。
品种编码:ZY_DAX 德指期货
二、环境说明
基于.NET 6+ 原生 ClientWebSocket 实现,无需第三方依赖。
三、完整实现代码
vbnet
using System;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace DaxQuoteClient
{
public class DaxWsClient
{
// WebSocket服务地址,仅代码内配置
private const string WsUrl = "ws://39.107.99.235/ws";
private const string Symbol = "ZY_DAX";
private const int HeartbeatInterval = 10000; // 10秒心跳
private const int ReconnectDelay = 3000; // 重连延迟3秒
private ClientWebSocket _ws;
private CancellationTokenSource _cts;
private Timer _heartbeatTimer;
public async Task StartAsync()
{
_cts = new CancellationTokenSource();
await ConnectAsync();
}
private async Task ConnectAsync()
{
try
{
_ws = new ClientWebSocket();
await _ws.ConnectAsync(new Uri(WsUrl), _cts.Token);
Console.WriteLine("WebSocket连接成功,订阅德指DAX行情");
// 发送订阅报文
var subMsg = $"{{\"Key\":\"{Symbol}\"}}";
await SendAsync(subMsg);
// 启动心跳定时器
_heartbeatTimer = new Timer(HeartbeatCallback, null, HeartbeatInterval, HeartbeatInterval);
// 启动接收循环
_ = ReceiveLoopAsync();
}
catch (Exception ex)
{
Console.WriteLine($"连接失败:{ex.Message},{ReconnectDelay}ms后重连");
await Task.Delay(ReconnectDelay);
await ConnectAsync();
}
}
private async void HeartbeatCallback(object state)
{
try
{
var ping = $"{{\"ping\":{DateTimeOffset.Now.ToUnixTimeSeconds()}}}";
await SendAsync(ping);
}
catch
{
// 心跳失败触发重连
_ = ReconnectAsync();
}
}
private async Task ReceiveLoopAsync()
{
var buffer = new byte[4096];
while (_ws.State == WebSocketState.Open && !_cts.IsCancellationRequested)
{
try
{
var result = await _ws.ReceiveAsync(new ArraySegment<byte>(buffer), _cts.Token);
if (result.MessageType == WebSocketMessageType.Text)
{
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
HandleMessage(message);
}
else if (result.MessageType == WebSocketMessageType.Close)
{
await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, _cts.Token);
}
}
catch (Exception ex)
{
Console.WriteLine($"接收异常:{ex.Message}");
break;
}
}
// 退出循环触发重连
_ = ReconnectAsync();
}
private void HandleMessage(string message)
{
try
{
using var doc = JsonDocument.Parse(message);
if (!doc.RootElement.TryGetProperty("body", out var body))
return;
var stockCode = body.GetProperty("StockCode").GetString();
var price = body.GetProperty("Price").GetString();
var high = body.GetProperty("High").GetString();
var low = body.GetProperty("Low").GetString();
var time = body.GetProperty("Time").GetString();
Console.WriteLine($"[{time}] {stockCode} 最新价:{price} 最高:{high} 最低:{low}");
}
catch (Exception ex)
{
Console.WriteLine($"解析异常:{ex.Message}");
}
}
private async Task SendAsync(string message)
{
var bytes = Encoding.UTF8.GetBytes(message);
await _ws.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, _cts.Token);
}
private async Task ReconnectAsync()
{
_heartbeatTimer?.Dispose();
_ws?.Dispose();
Console.WriteLine($"连接断开,{ReconnectDelay}ms后自动重连");
await Task.Delay(ReconnectDelay);
await ConnectAsync();
}
public void Stop()
{
_cts.Cancel();
_heartbeatTimer?.Dispose();
_ws?.Dispose();
}
}
class Program
{
static async Task Main(string[] args)
{
var client = new DaxWsClient();
await client.StartAsync();
Console.WriteLine("按任意键退出");
Console.ReadKey();
client.Stop();
}
}
}
四、核心返回字段
| 字段 | 说明 |
|---|---|
| StockCode | 品种编码 |
| Price | 最新价格 |
| Open | 开盘价 |
| LastClose | 昨结算价 |
| High | 日内最高价 |
| Low | 日内最低价 |
| Diff | 涨跌额 |
| DiffRate | 涨跌幅 |
| Time | 行情更新时间 |
五、开发注意事项
- 采用异步接收循环,避免同步阻塞导致的界面卡死或线程浪费;
- 10 秒定时心跳,防止服务端主动断开空闲连接;
- 所有异常都会触发重连逻辑,保证 7×24 小时稳定运行;
- 德指交易时间对应欧洲时区,国内夜间波动较大,业务告警注意时区;
- 生产环境建议替换 Console 输出为日志框架,比如 Serilog。
六、总结
本文基于.NET 原生 WebSocket 实现德指 DAX 期货实时行情监听,包含完整的心跳、重连、解析逻辑,无需第三方依赖,可直接集成到.NET 量化系统、行情大屏中。修改品种编码即可快速适配其他欧洲期货品种。