You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET通过进程启动Web API(真实TCP套接字)无法连接问题排查

排查步骤及解决方案

1. 端口不匹配(最直接的问题)

你的错误信息显示连接被拒绝的是localhost:5000,但测试代码里请求的是http://localhost:5083/WeatherForecast——说明API实际启动在5000端口,和你预期请求的端口完全不一致。

解决方法二选一:

  • 修改测试代码,请求API实际使用的5000端口;
  • 强制API启动在指定端口,修改dotnet run的参数:
    Arguments = "run --urls=http://localhost:5083",
    
    这样可以绕过launchSettings.json的默认配置,确保API固定启动在你需要的端口。

2. 硬编码延迟不可靠

Task.Delay(5000)是盲等逻辑,API可能还没完成启动初始化就被请求,导致连接失败。建议换成两种可靠的等待方式:

方案A:监听API启动日志

捕获API的输出,直到看到类似Now listening on: http://localhost:xxxx的启动完成日志,再发起请求:

private async Task<Process> StartProcessAndWaitForReady()
{
    var tcs = new TaskCompletionSource<bool>();
    var testProjectDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var apiProjectDir = Path.GetFullPath(Path.Combine(testProjectDir, "../../../../ProcessAPI"));

    var processStartInfo = new ProcessStartInfo
    {
        FileName = "dotnet",
        Arguments = "run --urls=http://localhost:5083",
        WorkingDirectory = apiProjectDir,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    };

    var process = new Process { StartInfo = processStartInfo };
    process.OutputDataReceived += (sender, args) =>
    {
        if (args.Data != null)
        {
            Console.WriteLine(args.Data);
            if (args.Data.Contains("Now listening on:"))
            {
                tcs.TrySetResult(true);
            }
        }
    };
    process.ErrorDataReceived += (sender, args) =>
    {
        if (args.Data != null) Console.WriteLine($"Error: {args.Data}");
    };
    process.Start();
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    // 设置30秒超时,避免无限等待
    await Task.WhenAny(tcs.Task, Task.Delay(TimeSpan.FromSeconds(30)));
    if (!tcs.Task.IsCompletedSuccessfully)
    {
        process.Kill();
        throw new InvalidOperationException("API启动超时");
    }
    return process;
}

方案B:重试请求

如果不想监听日志,可以给请求加重试逻辑,直到成功或超时:

// 在测试方法里替换请求逻辑
var response = await RetryAsync(() => client.GetAsync("http://localhost:5083/WeatherForecast"), 
                                maxRetries: 10, 
                                delayMs: 500);

// 重试方法实现
private async Task<HttpResponseMessage> RetryAsync(Func<Task<HttpResponseMessage>> action, int maxRetries, int delayMs)
{
    var retryCount = 0;
    while (true)
    {
        try
        {
            var response = await action();
            if (response.IsSuccessStatusCode)
                return response;
        }
        catch (HttpRequestException) when (retryCount < maxRetries)
        {
            retryCount++;
            await Task.Delay(delayMs);
        }
    }
}

3. 验证工作目录是否正确

相对路径../../../../ProcessAPI在不同环境(比如测试输出目录、CI流水线)可能无法正确定位到API项目。建议改为绝对路径:

var testProjectDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var apiProjectDir = Path.Combine(testProjectDir, "../../../../ProcessAPI");
// 转为绝对路径消除相对路径歧义
apiProjectDir = Path.GetFullPath(apiProjectDir);

把这个路径赋值给WorkingDirectory,确保Process能找到API项目文件。

4. 确认API是否真的启动

检查API的启动日志,看是否有启动失败的错误(比如依赖缺失、项目文件不存在)。如果用xUnit,可以注入ITestOutputHelper来记录日志,方便排查:

private readonly ITestOutputHelper _output;

public GetWeatherForecastTest(ITestOutputHelper output)
{
    _output = output;
}

// 在OutputDataReceived事件里替换输出逻辑
_output.WriteLine(args.Data);

这样就能在测试报告里看到API的完整启动日志,确认是否真的启动成功,以及实际监听的端口。


内容的提问来源于stack exchange,提问作者Isaac Richardson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:28:09