测试 HTTP 发送数据速率
static void http_iperf(void)
{
esp_http_client_config_t config = {
.url = "http://httpbin.org/post",
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_method(client, HTTP_METHOD_POST);
int count = 50;
size_t chunk1_data_size = 1024 * 50;
esp_http_client_open(client, chunk1_data_size * count);
char *chunk1_data = malloc(chunk1_data_size);
uint32_t start_timer = esp_log_timestamp();
int content_length, read_len;
char *buffer = malloc(1024);
ESP_LOGW(TAG, "---send begin---");
for (int i = 0; i < count; ++i) {
int wlen = esp_http_client_write(client, chunk1_data, chunk1_data_size);
if (wlen < 0) {
ESP_LOGE(TAG, "Write failed");
}
ESP_LOGI(TAG, "write_size: %d", wlen);
content_length = esp_http_client_fetch_headers(client);
// ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d", esp_http_client_get_status_code(client), content_length);
// read_len = esp_http_client_read(client, buffer, 1024);
// ESP_LOGI(TAG, "read_len: %d", read_len);
}
int cost_time = (esp_log_timestamp() - start_timer)/1000;
ESP_LOGW(TAG, "send end, cost time %d, speed %dKB/s", cost_time, chunk1_data_size * count/cost_time/1024);
esp_http_client_cleanup(client);
}
通过 HTTP 发送 chunked 数据
相关 API
/**
* @brief This function will write data to the HTTP connection previously opened by esp_http_client_open()
*
* @param[in] client The esp_http_client handle
* @param buffer The buffer
* @param[in] len This value must not be larger than the write_len parameter provided to esp_http_client_open()
*
* @return
* - (-1) if any errors
* - Length of data written
*/
int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len);
esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len)
{
client->post_len = write_len;
esp_err_t err;
if ((err = esp_http_client_connect(client)) != ESP_OK) {
return err;
}
if ((err = esp_http_client_request_send(client, write_len)) != ESP_OK) {
return err;
}
return ESP_OK;
}
static esp_err_t esp_http_client_request_send(esp_http_client_handle_t client, int write_len)
{
int first_line_len = 0;
if (!client->first_line_prepared) {
if ((first_line_len = http_client_prepare_first_line(client, write_len)) < 0) {
return first_line_len;
}
client->first_line_prepared = true;
client->header_index = 0;
client->data_written_index = 0;
client->data_write_left = 0;
}
...
static int http_client_prepare_first_line(esp_http_client_handle_t client, int write_len)
{
if (write_len >= 0) {
http_header_set_format(client->request->headers, "Content-Length", "%d", write_len);
} else {
esp_http_client_set_header(client, "Transfer-Encoding", "chunked");
esp_http_client_set_method(client, HTTP_METHOD_POST);
}
...
测试代码
idf 版本:v4.3.1
static void http_post_chunked_data()
{
esp_http_client_config_t config = {
.url = "https://siva.how2go.cn/",
.method = HTTP_METHOD_POST, // This is NOT required. write_len < 0 will force POST anyway
};
char buffer[1024] = {0};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_open(client, -1); // write_len=-1 sets header "Transfer-Encoding: chunked" and method to POST
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
return;
}
// Post some data
esp_http_client_write(client, "5", 1); // length
esp_http_client_write(client, "\r\n", 2);
esp_http_client_write(client, "Hello", 5); // data
esp_http_client_write(client, "\r\n", 2);
esp_http_client_write(client, "6", 1); // length
esp_http_client_write(client, "\r\n", 2);
esp_http_client_write(client, " World!", 7); // data
esp_http_client_write(client, "\r\n", 2);
esp_http_client_write(client, "0", 1); // end
esp_http_client_write(client, "\r\n", 2);
esp_http_client_write(client, "\r\n", 2);
// After the POST is complete, you can examine the response as required using:
int content_length = esp_http_client_fetch_headers(client);
ESP_LOGI(TAG, "content_length: %d, status_code: %d", content_length, esp_http_client_get_status_code(client));
int read_len = esp_http_client_read(client, buffer, 1024);
ESP_LOGI(TAG, "receive %d data from server: %s", read_len, buffer);
esp_http_client_close(client);
esp_http_client_cleanup(client);
}
运行结果如下:
I (7541) wifi:new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
I (7541) wifi:state: init -> auth (b0)
I (7551) wifi:state: auth -> assoc (0)
I (7561) wifi:state: assoc -> run (10)
I (7601) wifi:connected with iot, aid = 44, channel 1, BW20, bssid = 30:a2:c2:70:27:88
I (7601) wifi:security: WPA2-PSK, phy: bgn, rssi: -25
I (7601) wifi:pm start, type: 1
I (7681) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (8501) esp_netif_handlers: example_connect: sta ip: 192.168.3.18, mask: 255.255.255.0, gw: 192.168.3.1
I (8501) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.3.18
I (9501) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:32ae:a4ff:fe80:663c, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (9501) example_connect: Connected to example_connect: sta
I (9511) example_connect: - IPv4 address: 192.168.3.18
I (9511) example_connect: - IPv6 address: fe80:0000:0000:0000:32ae:a4ff:fe80:663c, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (9521) HTTP_CLIENT: Connected to AP, begin http example
I (10511) HTTP_CLIENT: content_length: 355, status_code: 200
I (10511) HTTP_CLIENT: receive 355 data from server: {
"args": {},
"data": "Hello World",
"files": {},
"form": {},
"headers": {
"Host": "httpbin.org",
"Transfer-Encoding": "chunked",
"User-Agent": "ESP32 HTTP Client/1.0",
"X-Amzn-Trace-Id": "Root=1-61c2da80-42eba34009b4325d137cefc6"
},
"json": null,
"origin": "20.187.154.207",
"url": "http://httpbin.org/post"
}
参考链接
Chunked transfer encoding
esp_http_client - How to POST Chunked Data
HTTP Stream