[ WiFi 智能家居项目 ] [ 9 ] WiFi HTTP 编程

背景

网页端对智能家居进行控制,需要使用 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 发送响应数据,分多次发送完成。

image.png

首先,发送 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);