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

Arduino(带以太网盾)发送JSON格式POST请求时请求体为空问题排查

问题分析与解决方案

我看了你的代码,发现两个违反HTTP协议规范的关键问题,这直接导致服务器无法正确解析你的POST请求体:

1. POST请求行缺少HTTP版本

HTTP请求的第一行必须明确指定版本信息,否则服务器可能无法按照标准逻辑处理请求。你原来的代码写的是:

client.println("POST /routes/test");

正确写法应该补充HTTP版本:

client.println("POST /routes/test HTTP/1.1");

2. 请求头与请求体之间的空行位置错误

HTTP协议要求:所有请求头发送完毕后,必须发送一个空行来分隔请求头和请求体。你的代码在POST行之后就提前发送了空行,这会让服务器误以为请求头已经结束,后续的Host、Content-Type等头信息都会被当成无效内容,而真正的JSON数据也无法被识别为请求体。

你原代码的错误顺序:

client.println("POST /routes/test");
client.println();  // 这里的空行位置完全错了!
client.println("Host: x.x.x.x");
...
client.println(measureJson(doc));
serializeJson(doc, client);

正确逻辑是:发送完所有请求头(包括Content-Length)之后,再发送空行,最后才发送JSON请求体。


修正后的完整代码

#include <ArduinoJson.h>
#include <Ethernet.h>
#include <SPI.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 10, 0, 0, 177 };
byte server[] = { x, x, x, x }; // 替换为你的服务器实际IP
EthernetClient client;

void setup() {
  // 初始化以太网并设置1秒延迟
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  delay(1000);

  Serial.println("connecting...");
  if (client.connect(server, 5000)) {
    Serial.println("connected");
  } else {
    Serial.println("connection failed");
    return; // 连接失败直接退出,避免后续无效操作
  }

  // 创建JSON文档并写入属性
  const size_t capacity = JSON_OBJECT_SIZE(1);
  DynamicJsonDocument doc(capacity);
  doc["name"] = "some random name";

  // 提前计算JSON长度,用于Content-Length字段
  size_t jsonLength = measureJson(doc);

  // 发送POST请求(已修正HTTP版本)
  Serial.println("Begin POST Request");
  client.println("POST /routes/test HTTP/1.1");
  // 发送所有请求头
  client.print("Host: ");
  client.println("x.x.x.x"); // 替换为你的服务器IP字符串
  client.println("User-Agent: Arduino/1.0");
  client.println("Content-Type: application/json;charset=UTF-8");
  client.println("Connection: close");
  client.print("Content-Length: ");
  client.println(jsonLength);

  // 关键:发送空行分隔请求头与请求体
  client.println();

  // 发送JSON请求体
  serializeJson(doc, client);

  // 修正笔误:把Get改成POST
  Serial.println("Sent POST Request");
}

void loop() {
  // 读取服务器响应,方便调试
  while (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    while(true); // 连接断开后停止程序
  }
}

额外说明

  • 我修正了你的笔误:把"Sent Get Request"改成了"Sent POST Request",避免混淆。
  • 添加了loop()函数来读取服务器的响应,这样你可以在串口看到服务器返回的信息,方便排查后续问题。
  • 连接失败后增加了return语句,避免后续代码继续执行浪费资源。

这些修改完全遵循HTTP 1.1协议规范,服务器应该能正确识别到你的JSON请求体了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:48:20