作者:王石
在《#跟着小白一起学鸿蒙# [二] 第一个OpenHarmony程序》我们熟悉了如何在开源鸿蒙开发应用,并通过hdc工具拷贝至开发板运行。但是那时候我们只是打印了最简单的hello world,接下来我们就讲开发最常用的部分,一个简单的http客户端;
概述
- HTTP 是一个基于 TCP/IP 通信协议来传递数据(HTML 文件、图片文件、查询结果等);
- HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出;
- HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息;
HTTP请求消息Request
- 请求数据结构如下
- 一个Get的sample
在浏览器输入www.baidu.com然后回车即可看到浏览器显示了百度的页面,按F12可以看到具体内容:
上图里我们可以看到在请求的url是www.baidu.com,请求的方法是GET,服务器的IP地址是180.101.49.14:443(https,若是http就是80)
-
一个Post的sample
上图里我们可以看到在请求的url是https://cysz.hopethink.com/qhhsd/app/getH5HsdList,请求的方法是POST,服务器的IP地址是114.215.124.251:443(https,若是http就是80),请求内容类型application/x-www-form-urlencoded;charset=UTF-8,请求数据长度84,请求数据keyword=&streetId=&pageNum=1&pageSize=1&ip=222.95.30.84
此样例参考小熊派设计,使用小熊派HM_Micro开发板进行验证
应用开发流程
graph LR
建立build.gn --> 建立helloworld.c --> 添加httpget --> 添加httppost --> 验证
-
建立Build.gn
import("//build/lite/config/component/lite_component.gni") executable("hello_world_lib") { output_name = "hello_world" sources = [ "hello_world.c" ] include_dirs = [] defines = [] cflags_c = [] ldflags = [] } lite_component("my_app") { features = [ ":hello_world_lib", ] }
-
建立helloworld.c
#include <stdio.h> int main(int argc, char **argv) { printf("\n************************************************\n"); printf("\n\t\tHello httpget!\n"); printf("\n************************************************\n\n"); return 0; }
-
添加httpget
int sockfd, ret, i, h; struct sockaddr_in servaddr; char str1[BUF_SIZE], str2[BUF_SIZE], buf[BUF_SIZE], *str; socklen_t len; fd_set t_set1; struct timeval tv; //创建套接字 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { printf("create socket failed--- exit(0)!\n"); exit(0); }; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); if (inet_pton(AF_INET, IPSTR_GET, &servaddr.sin_addr) <= 0 ){ printf("inet_pton failed --- exit(0)!\n"); exit(0); }; if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ printf("connect failed, exit(0)!\n"); exit(0); } printf("connect remote server\n"); memset(str2, 0, BUF_SIZE); strcat(str2, "theDataToGet"); str=(char *)malloc(BUF_SIZE); len = strlen(str2); sprintf(str, "%d", len); //请求头部内容 memset(str1, 0, BUF_SIZE); strcat(str1, "GET / HTTP/1.1\n"); strcat(str1, "Host: www.baidu.com\n"); strcat(str1, "Content-Type: text/html\n"); strcat(str1, "Content-Length: "); strcat(str1, str); //请求空行 strcat(str1, "\n\n"); //请求参数 strcat(str1, str2); strcat(str1, "\r\n\r\n"); printf("%s\n",str1); ret = write(sockfd,str1,strlen(str1)); if (ret < 0) { printf("socket write failed! errcode%d,errmsg'%s'\n",errno, strerror(errno)); exit(0); }else{ printf("socket write %d bytes!\n\n", ret); } FD_ZERO(&t_set1); FD_SET(sockfd, &t_set1); while(1) { sleep(2); h = 0; h = select(sockfd +1, &t_set1, NULL, NULL, &tv); if (h < 0) { close(sockfd); printf("SELECT error, return -1!\n"); return -1; }; if (h > 0){ memset(buf, 0, BUF_SIZE); i= read(sockfd, buf, BUF_SIZE); if (i==0){ close(sockfd); printf("read 0, return -1!\n"); return -1; } printf("%s\n", buf); } } close(sockfd); return 0;
-
httppost
int sockfd, ret, i, h; struct sockaddr_in servaddr; char str1[BUF_SIZE], str2[BUF_SIZE], buf[BUF_SIZE], *str; socklen_t len; fd_set t_set1; struct timeval tv; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { printf("create sockt failed---exit(0)!\n"); exit(0); }; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); if (inet_pton(AF_INET, IPSTR_POST, &servaddr.sin_addr) <= 0 ){ printf("inet_pton failed---exit(0)!\n"); exit(0); }; if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){ printf("connect server failed, exit(0)!\n"); exit(0); } printf("connect to server\n"); memset(str2, 0, BUF_SIZE); strcat(str2, "keyword=&streetId=&pageNum=1&pageSize=1&ip=222.95.30.84"); str=(char *)malloc(BUF_SIZE); len = strlen(str2); sprintf(str, "%d", len); //请求头部内容 memset(str1, 0, BUF_SIZE); strcat(str1, "POST /qhhsd/app/getH5HsdList HTTP/1.1\n"); strcat(str1, "Host: cysz.hopethink.com\n"); strcat(str1, "Content-Type: application/x-www-form-urlencoded\n"); strcat(str1, "Content-Length: "); strcat(str1, str); //请求空行 strcat(str1, "\n\n"); //str2的值为post的数据 strcat(str1, str2); strcat(str1, "\r\n\r\n"); printf("%s\n",str1); ret = write(sockfd,str1,strlen(str1)); if (ret < 0) { printf("socket write failed! errcode%d, errmsg'%s'\n",errno, strerror(errno)); exit(0); }else{ printf("socket write %d bytes\n\n", ret); } FD_ZERO(&t_set1); FD_SET(sockfd, &t_set1); tv.tv_sec= 0; tv.tv_usec= 0; h= 0; while(1) { sleep(2); h = select(sockfd +1, &t_set1, NULL, NULL, &tv); if (h == -1) { close(sockfd); printf("select error, return -1\n"); return -1; }; if ( FD_ISSET(sockfd, &t_set1) ){ memset(buf, 0, BUF_SIZE); i= read(sockfd, buf, BUF_SIZE); if (i==0){ close(sockfd); printf("read 0, return -1!\n"); return -1; } printf("%s\n", buf); } } close(sockfd); return 0;
-
在main里增加方法和头文件
-
头文件
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <time.h> #include <errno.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #define IPSTR_GET "180.101.49.14" //服务器IP地址,上面查出来的; #define IPSTR_POST "114.215.124.251" #define PORT 80 #define BUF_SIZE 4096
-
方法
httpget(); httppost();
-
-
测试结果
-
Get测试结果
-
Post测试结果
-
总结
- http是建立在socket之上的数据结构化应用协议,可以通过拼socket包实现所有功能;
- 之后我们可以利用此接口实现一个核算地图的界面应用;
参考链接:
https://gitee.com/bearpi/bearpi-hm_micro_app/blob/master/README.md
本文作者:左翼风发