TlsException:发送一堆网络请求后握手失败

问题描述 投票:0回答:1

在我发送大约 1500-1700 个网络请求后(始终在该范围内),我收到此错误:

TlsException: Handshake failed - error code: UNITYTLS_INTERNAL_ERROR, verify result: UNITYTLS_X509VERIFY_NOT_DONE

重新启动 Unity 会“刷新”配额,我可以再次发送大约相同数量的请求。

我正在构建一个网络爬虫,我需要发送大约 14000 个请求。 每个请求之间都有延迟,我最多同时发送 5 个请求,以避免服务器过载。

我也尝试了以下网站进行测试,但得到了同样的错误: https://httpbin.org/

这是我的 HttpClient:

private static readonly Lazy<HttpClient> httpClient = new(() => new HttpClient(new HttpClientHandler
{
    ServerCertificateCustomValidationCallback = (_, _, _, _) => true,
    ClientCertificateOptions = ClientCertificateOption.Automatic,
    SslProtocols = SslProtocols.None
})
{
    BaseAddress = new Uri("https://yugioh.fandom.com/"),
    Timeout = TimeSpan.FromSeconds(HTTPCLIENT_TIMEOUT),
    DefaultRequestHeaders =
    {
        ConnectionClose = true
    }
});

更改 HttpClient 中的设置(或根本没有自定义设置)并不能解决问题。

我读到 UnityWebRequest 可能没有这些问题,但它只能从主线程调用,我不想重构所有内容以使用协程。

编辑: 这是我用于发送请求和读取内容流的代码。

internal static async Task<CustomHttpStatusCode> DownloadAsync(URL _URL, Func<string, Task> _ProcessLine, Func<bool> _StopCondition, CancellationToken _CancellationToken)
{
    using var _cancellationTokenSource = new CancellationTokenSource();
    using var _linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_CancellationToken, _cancellationTokenSource.Token);

    var (_statusCode, _contentStream) = await DownloadAsStreamAsync(_URL, _linkedCancellationTokenSource.Token);

    if (_contentStream == null)
    {
        return _statusCode;
    }

    using (var _streamReader = new StreamReader(_contentStream))
    {
        while (await _streamReader.ReadLineAsync() is {} _currentLine)
        {
            await _ProcessLine(_currentLine);
    
            if (_StopCondition())
            {
                _cancellationTokenSource.Cancel();
                return CustomHttpStatusCode.Stopped;
            }
        }
    }

    return _statusCode;
}
private static async Task<(CustomHttpStatusCode StatusCode, Stream? ContentStream)> DownloadAsStreamAsync(URL _URL, CancellationToken _CancellationToken)
{
    var _semaphoreAcquired = false;
    var _attempt = 1;
    var _httpStatusCode = CustomHttpStatusCode.Null;
    Stream? _contentStream = null;
    
    do
    {
        try
        {
            await Task.Delay(1000, _CancellationToken);
            await semaphoreSlim.Value.WaitAsync(_CancellationToken);
            _semaphoreAcquired = true;
        
            // I can't add a "using" here since the stream would already be disposed when i try to access it in "DownloadAsync".
            var _response = await httpClient.Value.GetAsync(_URL.AbsoluteUri, HttpCompletionOption.ResponseHeadersRead, _CancellationToken);
            
            _httpStatusCode = _response.EnsureSuccessStatusCode().StatusCode.ToCustomHttpStatusCode(); 
            _contentStream = await _response.Content.ReadAsStreamAsync();
        
            return (_httpStatusCode, _contentStream);
        }
        catch (TaskCanceledException) when (_CancellationToken.IsCancellationRequested) { /* Expected behavior. */ }
        catch (Exception _exception)
        {
            Debug.LogException(_exception.CustomMessage($"Download attempt [{_attempt}] aborted: {_URL.Bold()} [{_httpStatusCode}]"));
            await Task.Delay(5000 * _attempt++, _CancellationToken);
        }
        finally
        {
            if (_semaphoreAcquired)
            {
                semaphoreSlim.Value.Release();
            }
        }
        
    } while (!_CancellationToken.IsCancellationRequested && _attempt <= 3);
    
    return (_httpStatusCode, _contentStream);
}
c# unity-game-engine x509certificate dotnet-httpclient handshake
1个回答
0
投票

这是Unity中的一个错误,错误报告如下: issuetracker.unity3d.com

© www.soinside.com 2019 - 2024. All rights reserved.