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

如何通过TCP发送含嵌套列表的对象调用HTTP POST接口?

基于TCP实现HTTP POST请求(无需等待响应)

需求说明

需要通过TCP直接发送HTTP POST请求,核心原因是无需等待服务端响应。目前已实现带参数的TCP GET请求,但需要改为发送包含两个对象列表的JSON请求体,调用HTTP POST接口。示例JSON请求体如下:

{
    "CustomerId" : 123,
    "CalendarYear" : 2023,
    "ExpensesA": [
        {"Id": "1", "Year": "2018", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "2", "Year": "2019", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "3", "Year": "2020", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "4", "Year": "2021", "Losses": "0", "Card": "0", "Taxes": "0"}
    ],
    "ExpensesB": [
        {"Id": "1", "Year": "2018", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "2", "Year": "2019", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "3", "Year": "2020", "Losses": "0", "Card": "0", "Taxes": "0"},
        {"Id": "4", "Year": "2021", "Losses": "0", "Card": "0", "Taxes": "0"}
    ]
}

现有TCP GET请求实现代码(C#):

using var tcp = new TcpClient("localhost", 12345);

using var stream = tcp.GetStream();

tcp.SendTimeout = 500;
tcp.ReceiveTimeout = 1000;

var resourceUri = new StringBuilder($"/Endpoint/{relativeUrl}");

resourceUri.Append($"?id={personId}");
resourceUri.Append($"&year={year}");

var builder = new StringBuilder();

builder.AppendLine($"GET {resourceUri} HTTP/1.1");
builder.AppendLine("Host: host.com");
builder.AppendLine("Connection: close");
builder.AppendLine();

var header = Encoding.ASCII.GetBytes(builder.ToString());

await stream.WriteAsync(header, 0, header.Length);

修改后的TCP POST实现代码

using System.Text;
using System.Text.Json;

// 定义与JSON结构匹配的实体类
public class ExpenseItem
{
    public string Id { get; set; }
    public string Year { get; set; }
    public string Losses { get; set; }
    public string Card { get; set; }
    public string Taxes { get; set; }
}

public class PostRequestData
{
    public int CustomerId { get; set; }
    public int CalendarYear { get; set; }
    public List<ExpenseItem> ExpensesA { get; set; }
    public List<ExpenseItem> ExpensesB { get; set; }
}

// 发送POST请求的方法
public async Task SendTcpPostRequest(string relativeUrl)
{
    using var tcp = new TcpClient("localhost", 12345);
    using var stream = tcp.GetStream();

    tcp.SendTimeout = 500;
    // 无需等待响应,将接收超时设为0
    tcp.ReceiveTimeout = 0;

    // 构造请求URL(POST参数一般放在请求体,URL保留固定路径即可)
    var resourceUri = $"/Endpoint/{relativeUrl}";

    // 构造请求体数据
    var requestData = new PostRequestData
    {
        CustomerId = 123,
        CalendarYear = 2023,
        ExpensesA = new List<ExpenseItem>
        {
            new ExpenseItem { Id = "1", Year = "2018", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "2", Year = "2019", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "3", Year = "2020", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "4", Year = "2021", Losses = "0", Card = "0", Taxes = "0" }
        },
        ExpensesB = new List<ExpenseItem>
        {
            new ExpenseItem { Id = "1", Year = "2018", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "2", Year = "2019", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "3", Year = "2020", Losses = "0", Card = "0", Taxes = "0" },
            new ExpenseItem { Id = "4", Year = "2021", Losses = "0", Card = "0", Taxes = "0" }
        }
    };

    // 序列化对象为UTF-8格式的JSON字节数组
    var jsonBytes = JsonSerializer.SerializeToUtf8Bytes(requestData);

    // 构造HTTP请求头
    var builder = new StringBuilder();
    builder.AppendLine($"POST {resourceUri} HTTP/1.1");
    builder.AppendLine("Host: host.com");
    builder.AppendLine("Connection: close");
    builder.AppendLine("Content-Type: application/json");
    builder.AppendLine($"Content-Length: {jsonBytes.Length}");
    builder.AppendLine(); // 空行分隔请求头与请求体

    // 将请求头转为字节数组
    var headerBytes = Encoding.ASCII.GetBytes(builder.ToString());

    // 先写入请求头,再写入请求体
    await stream.WriteAsync(headerBytes, 0, headerBytes.Length);
    await stream.WriteAsync(jsonBytes, 0, jsonBytes.Length);

    // 无需等待响应,写完直接关闭连接
    tcp.Close();
}

关键修改点说明

  • 请求方法变更:将GET改为POST,URL不再拼接查询参数(若需保留URL参数可继续添加,但POST数据优先放在请求体)。
  • 新增必要HTTP头:添加Content-Type: application/json告知服务端请求体格式,Content-Length指定请求体字节长度,这是服务端正确解析JSON的核心前提。
  • 序列化请求体:通过System.Text.Json(也可使用Newtonsoft.Json)将实体对象序列化为UTF-8格式的JSON字节数组。
  • 调整超时与连接逻辑:因无需等待响应,将ReceiveTimeout设为0,写完数据后直接关闭TCP连接即可。
  • 写入顺序规范:必须先写入HTTP请求头,再写入请求体,两者之间用空行分隔(对应代码中builder.AppendLine())。

内容的提问来源于stack exchange,提问作者DValdir Martins

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 23:15:01