httpclient源码介绍
前面介绍了hfs server的使用,本文使用设备系统为freertos,支持lwip协议,移植httpclient 后,从hfs server(这里本机电脑)获取文件。
httpclient主要存在两个结构体
//与建立网络连接相关,本文只看http,https省略(中间加层tls)
typedef struct {
int socket; /**< Socket ID. */
int remote_port; /**< HTTP or HTTPS port. */
int response_code; /**< Response code. */
char *header; /**< Request custom header. */
char *auth_user; /**< Username for basic authentication. */
char *auth_password; /**< Password for basic authentication. */
bool is_http; /**< Http connection? if 1, http; if 0, https. */
} httpclient_t;
//http通信数据有关
typedef struct {
bool is_more; /**< Indicates if more data needs to be retrieved. */
bool is_chunked; /**< Response data is encoded in portions/chunks.*/
int retrieve_len; /**< Content length to be retrieved.---代表某次请求剩余数据长度 */
int response_content_len; /**< Response content length. ---代表某次请求的总数据长度*//
int post_buf_len; /**< Post data length. */
int response_buf_len; /**< Response body buffer length.---单次传输长度 */
int header_buf_len; /**< Response head buffer lehgth. */
char *post_content_type; /**< Content type of the post data. */
char *post_buf; /**< User data to be posted. */
char *response_buf; /**< Buffer to store the response body data. */
char *header_buf; /**< Buffer to store the response head data. */
} httpclient_data_t;
httpclient主要api接口
HTTPCLIENT_RESULT httpclient_get(httpclient_t *client, char *url, httpclient_data_t *client_data);
HTTPCLIENT_RESULT httpclient_post(httpclient_t *client, char *url, httpclient_data_t *client_data);
HTTPCLIENT_RESULT httpclient_put(httpclient_t *client, char *url, httpclient_data_t *client_data);
HTTPCLIENT_RESULT httpclient_delete(httpclient_t *client, char *url, httpclient_data_t *client_data);
//上面接口均是由下面接口组成,先httpclient_connect,再request,最后等待response
HTTPCLIENT_RESULT httpclient_connect(httpclient_t *client, char *url);
HTTPCLIENT_RESULT httpclient_send_request(httpclient_t *client, char *url, int method, httpclient_data_t *client_data);
HTTPCLIENT_RESULT httpclient_recv_response(httpclient_t *client, httpclient_data_t *client_data);
测试代码(逻辑部分)
设备为freefros系统,支持lwip协议栈,移植httpclient后,从hfs server获取文件。并且打印文件数据。
#define HTTP_BUF_SIZE (1024 * 4)
char httpclient_download_file(char *http_url)
{
HTTPCLIENT_RESULT ret;
httpclient_t client = {0};
httpclient_data_t client_data = {0};
char status = -1;
char *buf;
char *file_buf = NULL;
int first_flag =0;
uint32_t count = 0;
uint32_t recv_temp = 0;
uint32_t data_len = 0;
int isfile_ok = -1;
//申请空间接收单次响应数据
buf = pvPortMalloc(HTTP_BUF_SIZE);
if (buf == NULL)
{
return;
}
// 根据url连接服务器
ret = httpclient_connect(&client, http_url);
if (!ret)
{
//申请空间,存储整个文件内容
file_buf = pvPortMalloc(1024*8);
if(file_buf == NULL)
{
goto fail;
}
client_data.response_buf = buf;
client_data.response_buf_len = HTTP_BUF_SIZE;
// 发送http get 请求
ret = httpclient_send_request(&client, http_url, HTTPCLIENT_GET, &client_data);
if (ret < 0){
goto fail;
}
do {
// 接收http get响应数据,注意单次接收最大HTTP_BUF_SIZE
memset(client_data.response_buf,0,HTTP_BUF_SIZE);
ret = httpclient_recv_response(&client, &client_data);
if (ret < 0){
break;
}
if (recv_temp == 0)
{
//当前数据长度
recv_temp = client_data.response_content_len;
}
//此次数据传输长度=当前数据长度-剩余数据长度
data_len = recv_temp - client_data.retrieve_len;
//剩余数据长度赋值为当前数据长度
recv_temp = client_data.retrieve_len;
printf("[%s]get len = %d\r\n",__func__,data_len);
if(client_data.response_content_len < 8*1024)
{
if(data_len >= 8*1024)
data_len = 8*1024;
if(count< 8*1024)
{
//将接收的数据copy到file_buf中
memcpy(file_buf+count, client_data.response_buf,data_len);
//记录file_buf中数据长度
count += data_len;
}
isfile_ok = 0;
}
else
{
count += data_len;
}
} while (ret == HTTPCLIENT_RETRIEVE_MORE_DATA);//判断http get请求数据是否传输完了
if (count != client_data.response_content_len || httpclient_get_response_code(&client) != 200) {
printf("data received not completed, or invalid error code \r\n");
status = -1;
goto fail;
}
else if (count == 0) {
printf("receive length is zero, file not found \n");
status = -2;
goto fail;
}
else {
printf("download success \n");
status = 1;
}
}
fail:
// Close http connection
httpclient_close(&client);
vPortFree(buf);
if((status == 1) && (isfile_ok == 0))
{
printf("[%s]total len=%d\r\n",__func__,count);
//打印http get获取文件的内容
printf("file buf:\n%s\n",file_buf);
}
if(file_buf)
vPortFree(file_buf);
printf("[%s]file download finish!\r\n",__func__);
// Print final log
if (ret >= 0)
if(IS_PRINTF)printf("httpclient_get_file.get file success.\r\n");
else
if(IS_PRINTF)printf("httpclient_get_file.get file fail.\r\n");
return status;
}
查看设备log
注意:打印文件有42个字节,原因在哪呢?
首先file.txt文件时windows下文件,其行末尾会加\r\n,linux文件只有\n,所以统计文件存在42个字节。
如图:
上述就完成了,使用http get给从服务器获取文件的一个简单测试。