当前位置: 首页 > 知识库问答 >
问题:

为什么Huobi服务器没有接收到C#WebSocket Ping?

卫才
2023-03-14

我正在尝试从火币 USDT 掉期流式传输比特币价格,但我的乒乓机制不起作用,所以火币总是在 30 秒后关闭连接。

文档是这么说的https://huobiapi . github . io/docs/usdt _ swap/v1/en/# market-heart beat:

WebSocket API支持双向心跳。服务器和客户端都可以发送ping消息,对方可以返回pong消息。

WebSocket Server 发送检测信号: {“ping”: 18212558000}

WebSocket客户端应该响应::{"pong":18212558000}

注意:一旦 WebSocket 客户端和 WebSocket 服务器连接好,服务器将每 5 秒发送一次检测信号(频率可能会更改)。如果 WebSocket 客户端忽略检测信号消息 5 次,则连接将自动断开连接。如果 WebSocket 客户端在最近的 2 条检测信号消息中响应一个“ping”值,则服务器将保持连接。

using System;
using System.IO;
using System.IO.Compression;
using System.Net.WebSockets;
using System.Text;
using System.Threading;

namespace HuobiMarketWebSocketTest
{
    class HuobiMarketWebSocketTest
    {
        public static void Main(string[] args)
        {
            int pings = 0;
            ClientWebSocket ClientWebSocket = new ClientWebSocket();
            string symbol = "btcusdt";
            ClientWebSocket.ConnectAsync(new Uri("wss://api.hbdm.com/linear-swap-ws"), CancellationToken.None).Wait();

            try
            {
                // Subscribe to BTC
                string subscribeTrade = $"{{ \"sub\": \"market.{symbol}.trade.detail\", \"id\": \"{symbol} trade\"}}";
                byte[] subscribeTradeAsBytes = Encoding.UTF8.GetBytes(subscribeTrade);
                ClientWebSocket.SendAsync(subscribeTradeAsBytes, WebSocketMessageType.Text, true, CancellationToken.None).Wait();
                Console.WriteLine($"{subscribeTrade} sent.");

                string subscribeQuote = $"{{ \"sub\": \"market.{symbol}.bbo\", \"id\": \"{symbol} bbo\"}}";
                byte[] subscribeQuoteAsBytes = Encoding.UTF8.GetBytes(subscribeQuote);
                ClientWebSocket.SendAsync(subscribeQuoteAsBytes, WebSocketMessageType.Text, true, CancellationToken.None).Wait();
                Console.WriteLine($"{subscribeQuote} sent.");

                ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[819200]);

                //Read from WebSocket
                while (ClientWebSocket.State == WebSocketState.Open)
                {
                    WebSocketReceiveResult receiveResult = ClientWebSocket.ReceiveAsync(bytesReceived, CancellationToken.None).Result;
                    byte[] compressedBytes = bytesReceived.Array[..receiveResult.Count];
                    byte[] decompressedBytes;

                    //Decompress json
                    using (MemoryStream compressedStream = new MemoryStream(compressedBytes))
                    {
                        using (GZipStream decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress))
                        {
                            using (MemoryStream decompressedStream = new MemoryStream())
                            {
                                decompressionStream.CopyTo(decompressedStream);
                                decompressedBytes = decompressedStream.ToArray();
                            }
                        }
                    }
                    string json = Encoding.UTF8.GetString(decompressedBytes);

                    // Handle ping
                    if (json.Contains("ping"))
                    {
                        pings++;
                        string pong = json.Replace("ping", "pong");
                        Console.WriteLine($"{json} received");
                        byte[] pongAsBytes = Encoding.UTF8.GetBytes(pong);
                        ClientWebSocket.SendAsync(pongAsBytes, WebSocketMessageType.Text, true, CancellationToken.None).Wait();
                        Console.WriteLine($"{pong} sent");
                        Console.WriteLine($"{pings} pings received");
                    }
                    else
                    {
                        // Uncomment to see that subscription worked
                        //Console.WriteLine(json);
                    }
                }
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);

                Console.WriteLine($"Huobi closed WebSocket after {pings} pings.");
            }
        }
    }
}

这是我的程序的输出:

{ "sub": "market.btcusdt.trade.detail", "id": "btcusdt trade"} sent.
{ "sub": "market.btcusdt.bbo", "id": "btcusdt bbo"} sent.
{"ping":1627090272242} received
{"pong":1627090272242} sent
1 pings received
{"ping":1627090277234} received
{"pong":1627090277234} sent
2 pings received
{"ping":1627090282238} received
{"pong":1627090282238} sent
3 pings received
{"ping":1627090287239} received
{"pong":1627090287239} sent
4 pings received
{"ping":1627090292238} received
{"pong":1627090292238} sent
5 pings received
{"ping":1627090297241} received
{"pong":1627090297241} sent
6 pings received
System.AggregateException: One or more errors occurred. (The remote party closed the WebSocket connection without completing the close handshake.)
 ---> System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake.
   at System.Net.WebSockets.ManagedWebSocket.ThrowIfEOFUnexpected(Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.EnsureBufferContainsAsync(Int32 minimumRequiredBytes, CancellationToken cancellationToken, Boolean throwOnPrematureClosure)
   at System.Net.WebSockets.ManagedWebSocket.ReceiveAsyncPrivate[TWebSocketReceiveResultGetter,TWebSocketReceiveResult](Memory`1 payloadBuffer, CancellationToken cancellationToken, TWebSocketReceiveResultGetter resultGetter)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at HuobiMarketWebSocketTest.HuobiMarketWebSocketTest.Main(String[] args) in C:\home\source\csharp\prog\HuobiMarketWebSocketTest - pong not recieved\HuobiMarketWebSocketTest\HuobiMarketWebSocketTest\HuobiMarketWebSocketTest.cs:line 156
Huobi closed WebSocket after 6 pings.

共有1个答案

班宏毅
2023-03-14

断开连接是因为.NETClientWebSocket在内部使用ManagedWebSocket,作为其保持活动处理的一部分,ManagedWebSocket会发送一个未经请求的pong帧。根据websocket标准,这是正确的行为。然而,这似乎会导致Huobi的期货和掉期(但不是现货)服务器出现问题。如果设置ClientwebSocket.Options。KeepAliveInterval到TimeSpan。零-这避免了ManagedWebSocket创建保活计时器,从而阻止设置未经请求的pong帧。这样做的缺点是会话从双向心跳转变为单向心跳,但由于在应用程序级别存在心跳,因此没有真正的缺点。

 类似资料:
  • 我正在使用Springboot和Java8 我有以下url,它与邮递员配合得很好: "http://localhost:8888/gc/goods/getAll" 现在我尝试编写一个自动测试: 当邮递员给我所有的数据回来,我得到以下错误从我的测试: 组织。springframework。网状物客户ResourceAccessException:获取请求“”时发生I/O错误http://localh

  • 我正在为一个大学项目使用Java编写POP3和SMTP服务器。我可以通过客户端(例如:Thunderbird)使用我的SMTP服务器发送电子邮件,我的服务器发送邮件时没有任何问题。 当外部发件人代理(如gmail或hotmail)尝试使用我的SMTP服务器发送电子邮件时,它不会完成通信,因为它会在邮件命令之后发送QUIT命令。为什么外部代理会这么做?我没有遵守SMTP协议吗? 问题是,当我收到来自

  • 命令: 给出了错误: 但是运行sudo权限,工作: 有没有可能因为sudo要求阻止我在intellij中打开数据库而放弃它?在回答这个问题时,我尝试了以下方法:不使用sudo连接到本地MySQL服务器: 这没有帮助。上面的问题抛出了一个不同的错误

  • 使用依赖关系spring-cloud-starter-zipkin,应用程序应该在sleuth触发时连接到zipkin服务器。我没有启动zipkin服务器,所以它应该抛出一个连接异常。但什么也没发生。而当我启动zipkin服务器时,它不能接收任何东西。 应用程序.属性 和日志

  • 我在Android上制作了一个客户端-服务器应用程序的简单原型 我设法将两个客户端连接到服务器上,服务器可以接收它们的消息。现在的问题是,我似乎无法向其他客户端广播/接收消息。 下面是Server类的完整代码 下面是Client类的完整代码

  • 问题内容: 我使用JDBC连接到MySQL。在时,一切正常。 但是,当我将应用程序移动到Intranet中的另一台计算机上并用于连接到MySQL数据库时,大约需要1分钟才能成功连接到MySQL。这是怎么回事? 问题答案: 好吧,这可能是DNS问题。您可以通过从配置文件中的选项开始禁用DNS主机名查找。 在这里阅读更多详细信息:http : //dev.mysql.com/doc/refman/5.