1.前言
【2014年4月重写该博文】
曾想使用STM32+LwIP实现一个yeelink应用,但是基础知识不够所以只能耐心学习。提到LwIP自然想到socket套接字,为了降低学习难度便从windwos平台的套接字开始入手。本文使用windows平台的套接字实现向eelink平台请求开关量状态,然后把HTTP响应打印至控制台。
【相关博文】
【 MinGW安装和使用总结 】
【Yeelink Http请求格式分析】
【Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32 】
2.运行
【工作流程】
先看运行结果,大致的过程分为三块。第一部分,进行DNS地址解析;第二部分,发送HTTP请求;第三部分,接收HTTP响应。
图1 运行结果
【运行设置】
若使用minGW+eclipse开发方式,需要加入wsock32库,添加的方法如下:
3.参考代码
int main(int argc, char **argv)
{
WSADATA wsaData;
int result_id;
int socket_id;
// HTTP请求
char send_buf[] =
"GET /v1.0/device/1949/sensor/2511/datapoints HTTP/1.1\r\n"
"U-ApiKey: [your apikey]\r\n"
"Host: api.yeelink.net\r\n\r\n";
// HTTP响应
char receive_buf[1024];
struct hostent *yeelink_host; // yeelink主机DNS解析结构体
char *host_name = "api.yeelink.net"; // yeelink域名
struct in_addr yeelink_ipaddr; // yeelink IP地址
struct sockaddr_in yeelink_sockaddr; // yeelink 连接套接字
// Winsows下启用socket
result_id = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result_id != 0) {
printf("WSAStartup failed: %d\n", result_id);
return 1;
}
// 第一步 DNS地址解析
printf("calling gethostbyname with: %s\r\n", host_name);
yeelink_host = gethostbyname(host_name);
if (yeelink_host == NULL)
{
// DNS解析失败
printf("error\r\n");
}
else
{
// DNS解析正确
yeelink_ipaddr.s_addr = *(u_long *) yeelink_host->h_addr_list[0];
printf("Yeelink IP Address %s\r\n" , inet_ntoa(yeelink_ipaddr));
}
// 第二步 创建套接字
socket_id = socket(AF_INET, SOCK_STREAM, 0);
yeelink_sockaddr.sin_family = AF_INET;
yeelink_sockaddr.sin_port = htons(80); // 设置端口号
yeelink_sockaddr.sin_addr = yeelink_ipaddr; // 设置IP地址
memset(&(yeelink_sockaddr.sin_zero), 0, sizeof(yeelink_sockaddr.sin_zero));
// 第三步 连接yeelink
result_id = connect( socket_id, (struct sockaddr *)&yeelink_sockaddr, sizeof(struct sockaddr));
if( result_id == SOCKET_ERROR )
{
printf("connect ok\r\n");
}
printf("Http request:\r\n%s\r\n",send_buf);
// 第四步 发送HTTP请求
send(socket_id , send_buf,strlen(send_buf), 0);
// 第五步 接收HTTP响应
int bytes_received = 0;
bytes_received = recv( socket_id , receive_buf , 1024 , 0);
receive_buf[ bytes_received ] = '\0';
printf("Receive Message:\r\n%s\r\n",receive_buf );
closesocket(socket_id); // 关闭套接字
WSACleanup(); // windows下释放套接字
getchar(); // 保持控制台窗口
return 0;
}
4.若干说明
【关于HTTP请求】
注意请求的最后部分一定是连续两组\r\n,如果查看相关文档的话,HTTP请求以一空行结束(\r\n),考虑到上一行的回车换行所以是两组\r\n。
【关于struct in_addr】
可理解为一个IP地址,一个IP地址为一个32位整数。
【关于struct sockaddr_in】
可理解为套接字信息,一个套接字可能包括目标IP地址、端口号和协议类型等信息。所以struct sockaddr_in要比struct in_addr所占的字节数更大一些。
【关于struct hostent】
保存DNS解析结果的结构体,其中最为关键的域名的P地址存于h_addr_list数组中,由于一个域名可能对应多个IP地址,可取h_addr_list数组中的第一个(下标为0)。
5.总结
熟悉了windows环境下的套接字编程,那么借助RT Thread轻松实现STM32+LwIP的方式和yeelink交互数据。
6.参考资料
【Yeelink Http请求格式分析】
【Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32 】——后续博文