网页端对智能家居进行控制,需要使用 HTTP 编程,实现 GET 和 POST 方法。
基本流程和前几个章节相同,主要有以下几点需要注意:
1. 域名解析
// 4. DNS
char* ipaddr;
struct hostent* phostent;
phostent = gethostbyname("www.baidu.com");
if (phostent != NULL) {
int i;
for (i = 0; phostent->h_addr_list[i]; ++i) {
ipaddr = inet_ntoa(*(struct in_addr*)(phostent->h_addr_list[i]));
if (ipaddr != NULL) {
printf("ipaddr = %s\n", ipaddr);
break;
}
}
if (ipaddr == NULL) {
printf("get ipaddr error!\n");
vTaskDelete( NULL );
return;
}
} else {
printf("httpcliet gethostbyname error\n");
vTaskDelete( NULL );
return;
}
2. 端口号
// 4. config server info
struct sockaddr_in myaddr;
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = PF_INET;
myaddr.sin_port = htons(80);
myaddr.sin_addr.s_addr = inet_addr(ipaddr);
myaddr.sin_len = sizeof(myaddr);
3. 内存申请
接收 server 返回数据,申请大数组,要在函数外申请,具体原因:
函数外申请数组,是在堆上进行申请;函数内,则是在栈上。
4. http 请求
client 向 server 请求数据时,只需向 server 发送请求头即可。
char buf[128] = "GET /index.html HTTP/1.1\r\nHost:baidu.com\r\n\r\n";
ret = send(fd, buf, sizeof(buf), 0);
5. http 响应
server 向 client 发送响应数据,分多次发送完成。
首先,发送 200 OK 报头,告知 client 连接成功。
// 发送200 ok报头
int file_ok(int cfd, long flen)
{
char *send_buf = zalloc(sizeof(char)*100);
sprintf(send_buf, "HTTP/1.1 200 OK\r\n");
send(cfd, send_buf, strlen(send_buf), 0);
sprintf(send_buf, "Connection: keep-alive\r\n");
send(cfd, send_buf, strlen(send_buf), 0);
sprintf(send_buf, "Content-Length: %ld\r\n", flen);
send(cfd, send_buf, strlen(send_buf), 0);
sprintf(send_buf, "Content-Type: text/html\r\n");
send(cfd, send_buf, strlen(send_buf), 0);
sprintf(send_buf, "\r\n");
send(cfd, send_buf, strlen(send_buf), 0);
printf("file ok end...\n");
free(send_buf);
return 0;
}
然后,响应 client 请求页面。
char buf[512] =
"<html>\r\n"
"<title>hello world</title>\r\n"
"<body>\r\n"
"<h1> hahaha\r\n"
"</body>\r\n"
"</html>\r\n";
// 9. send data to client
ret = send(cfd, buf, sizeof(buf), 0);
最后,需要将 accept 返回新的文件描述符关闭,不然 client 会一直处于连接状态。
close(cfd);