使用HTTP获取Web服务

HTTP(超文本)协议

概念

一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网送万维网文档的数据传送协议

简单快速:客户端向服务器请求服务时,只需要传送请求方法和路径,常用方法:GET,POST

GET,又叫明文,请求的信息是不加密的

POST,又叫密文,请求的信息是加密的

无连接:限制每次链接只处理一个请求

无状态:即如果后续处理需要前面的信息,它必须重传,这样可能每次连接传输的数据量会增大(采用多线程的方法解决)


HTTP请求头部:

wemeetapp_uLjIYKzMXL.png

Untitled

\r\n 在每一行的末尾
URL:统一资源标识符
Method 方法
请求行格式:”请求方法“ URL/URI 版本 \r\n
Host:向那个服务器做请求
头部字段1: Host:www.w3.org \r\n


HTTP协议的请求方法常见的有GET、HEAD、POST、PUT等,每种请求方法的规则各不相同

wemeetapp_VcXA0IK8eI.png


URL:http: + // + web服务器 + / + 目录名 + / +... (路径)
最后没东西了,还要加 \r\n

Untitled


HTTP/1.1 是主流版本,因为是长连接 ,请求后不会自动断开
持久连接
http是建立在tcp之上,所以需要利用TCP协议连接到服务器,通多getsockopt()函数解析域名


客户端必须指定Host字段: Host : 主机域名 \r\n 比如 “Host: www.baidu.com\r\n”
双方建立连接,此时可以利用HTTP协议发送请求信息,并等待服务器的响应,基于请求/响应


请求行:GET URL HTTP/1.1\r\n
请求字段:Host:api.seniverse.com\r\n

注意:因为复制原因所以反斜杠多了一个应该是 \r\n 的格式

wemeetapp_yJk2vWvIEh.png

Untitled


HTTP状态编码

服务器响应的数据报文中存在状态码,用户通过状态码可以知道服务器的响应状态,在HTTP标准中有对应的状态码类型,如下:

Untitled

Untitled

Untitled

当客户端接收到服务器的响应报文之后,可以根据响应报文中的状态码分析可能存在的问题并针对性解决。

HTTP的基本应用

Untitled

Untitled


Web编程客户端(获取心知天气)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>

#define ERR_LOG(errmsg)                                     \
    do                                                      \
    {                                                       \
        perror(errmsg);                                     \
        printf("%s,%s,%d\n", __FILE__, __func__, __LINE__); \
        exit(1);                                            \
    } while (0)

#define N 1024

#define API_KEY "your_api_key"
#define LOCATION "your_location"
#define GET_URL(key, location) "GET https://api.seniverse.com/v3/weather/now.json?key=" key "&location=" location "&language=zh-Hans&unit=c "

int main(int argc, char const *argv[])
{

    // 判断参数个数是否正确
    if (argc != 3)
    {
        printf("Usage: %s <port> <ip>\n", argv[0]);
        exit(1);
    }
    printf("port: %s\n", argv[1]);

    // 可以添加域名解析

    // 创建套接字
    int cli_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (cli_fd == -1)
    {
        ERR_LOG("socket");
        return -1;
    }

    // 连接服务器
    struct sockaddr_in ser_inf;
    memset(&ser_inf, 0, sizeof(ser_inf));

    ser_inf.sin_family = AF_INET;                 // 协议族
    ser_inf.sin_port = htons(atoi(argv[1]));      // 服务器端口号
    ser_inf.sin_addr.s_addr = inet_addr(argv[2]); // 服务器IP地址

    if (connect(cli_fd, (struct sockaddr *)&ser_inf, sizeof(ser_inf)) == -1)
    {
        ERR_LOG("connect");
        return -1;
    }

    // 创建文件描述符集合
    fd_set fdset;

    // 清空文件描述符集合
    FD_ZERO(&fdset);

    // 把要添加监听的文件描述符添加到集合里面
    FD_SET(cli_fd, &fdset); // 接收消息你要把那个文件描述符添加进去进行监听

    // 用于存储HTTP请求内容:请求行+请求头+\r\n+请求包体(可选)
    char msg[N];

    sprintf(msg, GET_URL(API_KEY, LOCATION) "HTTP/1.1"
                                            "\r\n"
                                            "Host: api.seniverse.com\r\n"
                                            "\r\n");

    // 开始实时轮询监听
    while (1)
    {
        // 清空文件描述符集合
        FD_ZERO(&fdset);

        // 把要添加监听的文件描述符添加到集合里面
        FD_SET(cli_fd, &fdset); // 接收消息你要把那个文件描述符添加进去进行监听

        // 监控的文件描述符范围是从 0 到 nfds-1。通常设置为所监控的文件描述符中最大值加 1。
        if (select(cli_fd + 1, &fdset, NULL, NULL, NULL) == -1)
        {
            ERR_LOG("select");
            return -1;
        }

        if (FD_ISSET(cli_fd, &fdset))
        {
            bzero(msg, N);
            recv(cli_fd, msg, N, 0);
            printf("%s\n", msg); // 响应头部信息
            bzero(msg, N);
            recv(cli_fd, msg, N, 0);
            printf("%s\n", msg); // 响应包体信息
        }
    }

    // 关闭套接字
    close(cli_fd);

    return 0;
}

posted @ 2024-06-14 11:01  晖_IL  阅读(10)  评论(0编辑  收藏  举报