【问题标题】:C# application getting disconnected from local api, usure how to reconnect without restarting the programC# 应用程序与本地 api 断开连接,使用如何在不重新启动程序的情况下重新连接
【发布时间】:2020-10-03 13:52:40
【问题描述】:

大家好,我是 c# 新手,前 2 周我已经完成了这门语言的学习,所以我的知识非常基础。

我正在玩一个连接到客户端(英雄联盟客户端)并使用各种方法发送和获取信息(获取、发布、放置和删除)的应用。

程序的作用:

  1. 应用启动后,会在加载表单时调用一个公共类。

public LCU lcu = new LCU();(我会在下面添加LCU的代码)

  1. 我可以发送任意数量的请求,这是一个工作示例:

var request = await lcu.http_client.DeleteAsync(lcu.baseURL + "/lol-lobby/v2/lobby").ConfigureAwait(true);

我的问题是,当我发出太多请求(每 2 秒或以下)时,应用程序与客户端/api 断开连接,要解决这个问题,我需要一个重新连接的任务。

现在我不知道该怎么做,我尝试在计时器内添加LCU lcu = new LCU();,但没有奏效。

我很想知道为什么它不起作用,如果您对如何做有一些建议,我会很高兴知道。

谢谢!!

LCU.cs(不是主要形式)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace LeaguePW5
{
    public class LCU
    {
        public string address { get; set; }
        public int port { get; set; }
        public string username { get; set; }
        public string password { get; set; }
        public string protocol { get; set; }
        public string process_name { get; set; }
        public int process_id { get; set; }
        public string baseURL => string.Format("{0}://{1}:{2}", this.protocol, this.address, this.port);
        public LCU()
        {
            Process[] process = Process.GetProcessesByName("LeagueClientUx");
            if (process.Length != 0)
            {
                string lockFile;
                using (FileStream stream = File.Open(Path.Combine(Path.GetDirectoryName(process[0].MainModule.FileName), "lockfile"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    lockFile = new StreamReader(stream).ReadToEnd();
                }
                string[] parameters = lockFile.Split(new string[] { ":" }, StringSplitOptions.None);
                this.username = "riot";
                this.address = "127.0.0.1";
                this.process_name = parameters[0];
                this.process_id = Convert.ToInt32(parameters[1]);
                this.port = Convert.ToInt32(parameters[2]);
                this.password = parameters[3];
                this.protocol = parameters[4];
            }

        }
        public HttpClient http_client
        {
            get
            {
                HttpClientHandler httpClientHandler = new HttpClientHandler();
                httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
                httpClientHandler.ServerCertificateCustomValidationCallback = ((HttpRequestMessage httpRequestMessage, X509Certificate2 cert, X509Chain cetChain, SslPolicyErrors policyErrors) => true);
                return new HttpClient(httpClientHandler)
                {
                    DefaultRequestHeaders =
                    {
                        Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("riot:" + this.password)))
                    }
                };
            }
            set
            {
            }
        }



    }
}

P.S.如果你需要完整的代码,我很乐意分享

【问题讨论】:

  • 在 LCU 类中添加 dispose 方法。
  • Http 连接不是持久的,每个请求都会创建一个新连接,除非标头“connection”未设置为“close”。有时,如果您在路由器或防火墙后面,连接池机制可能会导致问题,在这种情况下,您可以做的最好的事情是确保每个请求都在新连接中执行,为此在客户端中添加“ConnectionClose = true”@ 987654325@

标签: c# api reconnect


【解决方案1】:

http_client 初始化有误。每次您发出请求时它都会返回新实例。

根据HttpClient 文档:

// HttpClient is intended to be instantiated once per application, rather than per-use.

尝试此修复程序,您将不会断开连接。 (此外,我还为属性应用了命名策略,微软在 .NET 中广泛使用)

private HttpClient _httpClient; // backing field
public HttpClient HttpClient
{
    get
    {
        if (_httpClient == null) // create new instance only if still not created
        {
            HttpClientHandler httpClientHandler = new HttpClientHandler();
            httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
            httpClientHandler.ServerCertificateCustomValidationCallback = ((HttpRequestMessage httpRequestMessage, X509Certificate2 cert, X509Chain cetChain, SslPolicyErrors policyErrors) => true);
            _httpClient = new HttpClient(httpClientHandler)
            {
                DefaultRequestHeaders =
                {
                    Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("riot:" + this.password)))
                }
            };
        }
        return _httpClient;
    }
}

及用法

await lcu.HttpClient.DeleteAsync(lcu.baseURL + "/lol-lobby/v2/lobby").ConfigureAwait(false);

ConfigureAwait(true) 是默认值。使用false 或不使用ConfigureAwait 以避免冗余开销。

此外,您可以从IDisposableimplement 接口派生LCU 类,因为HttpClientIDisposable。并在处理方法中调用HttpClient.Dispose()。但只有在您多次创建 new LCU() 类时才有意义。

【讨论】:

  • 非常感谢您的超级回答!这有点复杂,但我很快就会研究它。 @Gusman 的回答非常好
  • @Germ 通过我的修复,您可以删除 ConnectionClose = true,并且您可能会获得性能提升。因为HttpClient 将重用已经打开的现有 TCP 连接,而不是为每个请求建立新的连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
相关资源
最近更新 更多