实用小技巧 | 用socket玩转http接口
一、前言
曾几何时,HTTP这种应用层协议对于我来说有点高级,总觉得调用 HTTP 接口是一件很难实现的事情,需要用一个很牛逼的库才行。
直到昨天我学习了一个骚操作,原来用 socket 就可以直接玩 http,赶紧分享一波~
开门见山,用socket玩转http接口就四步:
- ① 建立 tcp 链接;
- ② 发送请求数据(请求报文);
- ③ 接收响应数据(响应报文);
- ④ 关闭 tcp链接,从接收数据中提取有效信息。
接下来一步一步开始玩。
二、请求报文和响应报文
1. 发送什么
建立 TCP 之后,要向服务器发送请求报文。请求报文的格式非常重要,稍微偏差服务器就不认,返回一堆其它的东西,比如错误码,404 not found等。
HTTP请求报文的格式如图:
(图片来源于网络)
主要包括四部分:
- 请求行:由请求方法(GET或者POST)、URI(注意不是URL)、HTTP协议版本(HTTP/1.1)组成,中间使用空格分离,末尾换行;
- 请求头部:一些字段及其值,每个字段占一行;
- 空行:表示请求报文结束;
- 请求体:POST方法时需要,GET方法时不需要。
2. 接收什么
HTTP 服务器收到请求报文后,会返回对应的结果,称之为响应报文:
(图片来源于网络)
在嵌入式设备中通常是从返回结果中提取有效信息,并且大多数API接口返回都是json数据格式,所以不用过于关心响应报文。
话不多说,直接开干!
三、用网络调试助手测试
1. 测试文件
我在博客服务器上放置了一个txt文件用于测试,读者如有兴趣也可以使用,地址在:
“http://www.mculover666.cn/hello.txt ”
使用浏览器访问结果如图:
2.2. 建立TCP链接
使用网络助手建立TCP链接,ip地址为服务器ip,端口默认为80端口,如图:
2.3. 发送请求报文
根据第二节的请求报文格式+要请求的URL,组装出要发送的内容如下:
GET /hello.txt HTTP/1.1
HOST:www.mculover666.cn
2.4. 处理请求报文
发出请求报文之后,服务器收到后返回的响应报文如下:
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 20 Sep 2020 11:30:32 GMT
Content-Type: text/plain
Content-Length: 44
Last-Modified: Sat, 19 Sep 2020 14:26:02 GMT
Connection: keep-alive
ETag: "5f6614fa-2c"
Accept-Ranges: bytes
you get success! nb! say from mculover666!
至于怎么对收到的数据进行解析,这就要秀出你的字符串解析功底了,比如strstr、sscanf、使用FIFO缓冲之后解析等骚操作。
好在物联网设备中大部分时候都是返回JSON内容或者文件内容。
四、使用TencentOS-tiny对接
常用的物联网操作系统都提供了基本的 TCP socket通信功能,这里我使用 TencentOS-tiny + ESP8266进行测试。
“测试前请保证socket可以正常通信。 ”
编写如下应用代码:
void application_entry(void *arg)
{
int ret = -1;
int socket_id = -1;
esp8266_sal_init(HAL_UART_PORT_0);
esp8266_join_ap("Tencent-WIFI", "424424424");
/* start connect */
socket_id = tos_sal_module_connect("122.51.89.94", "80", TOS_SAL_PROTO_TCP);
if (socket_id == -1) {
printf("TCP0 connect failedrn");
} else {
printf("TCP0 connect success! fd: %dn", socket_id);
}
/* send request */
ret = tos_sal_module_send(socket_id, (const void*)REQUEST_DATA, strlen(REQUEST_DATA));
if (ret < 0) {
printf("send failrn");
} else {
printf("send success, %d bytesrn", ret);
}
/* recv response */
ret = tos_sal_module_recv_timeout(socket_id, recv_data_buf, sizeof(recv_data_buf), 8000);
if (ret < 0) {
printf("task1 receive errornr");
} else if (ret == 0) {
printf("task1 receive nonen");
} else {
recv_data_buf[ret] = 0;
printf("task1: receive len: %dnmsg from remote: %sn", ret, recv_data_buf);
}
/* close socket */
tos_sal_module_close(socket_id);
}
编译,下载到开发板中,在串口助手中查看结果:
怎么样,HTTP玩起来是不是很简单?
本文只是提供一种行之有效的思路,请求报文中的字段还有很多,需要查阅类似HTTP协议详解的文章去探索、测试,这里不做过多讲解。
感兴趣的读者可以再找点API接口玩玩哈哈~学业繁忙,告辞!
- 为安全出把力:CVE-2011-1938漏洞分析以及exp编写
- 10.13 netfilter5表5链介绍
- 用JAVA测量DEA页面的社交媒体流行度
- Java数组赋值
- 10.12 firewalld和netfilter
- 10.11 Linux网络相关
- 利用Crypto++实现RSA加密算法
- 重学javascript 红皮高程(6)
- WriteUp分享 | LCTF的一道preg_match绕过+出题人的锅
- 利用crypto++库实现AES加密算法
- Android之倒计时CountdownTimer用法
- WriteUp分享 | LCTF的一道padding oracle攻击+sprintf格式化字符串导致的SQL注入
- 10.27 target介绍
- Android 之游戏开发流程
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 10 种常用 Matplotlib 图的 Python 代码
- Python爬取某宝商品数据案例:100页的价格、购买人数等数据
- 如何让你的图片加上一层天气的特效?Python帮你解决(附源码)
- Python最简单的图片爬虫,20行代码带你爬遍整个网站
- 用Python把人物头像动漫化,不同的表情给你不同的惊喜
- python苦短-爬取音乐
- python苦短-灵笼说啥
- python爬虫-八佰词云
- python爬虫-beautifulsoup使用
- 深度学习-卷积神经网络原理
- 深度理论VGG-NET 网络
- 只要30行代码!7步教会你Python爬取网页抖音热门视频
- python苦短-CV2
- python实现语音在线合成,让你的小说自己念给你听
- Python爬虫实战:模拟登录淘宝网站