C 语言实现 HTTP 和 HTTPS 通信的例程

HTTP 通信例程

HTTP 是一种明文传输协议,在 C 语言中可以使用 socket 编程来实现简单的 HTTP 请求。以下是一个示例代码,用于向指定的 HTTP 服务器发送 GET 请求并接收响应:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];
    char request[BUFFER_SIZE];

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        return -1;
    }

    // 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(80); // HTTP 默认端口
    if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
        perror("invalid address or address not supported");
        return -1;
    }

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connection failed");
        return -1;
    }

    // 构建 HTTP 请求
    snprintf(request, sizeof(request), "GET / HTTP/1.1\r\n"
                                       "Host: 127.0.0.1\r\n"
                                       "Connection: close\r\n\r\n");

    // 发送请求
    if (send(sockfd, request, strlen(request), 0) == -1) {
        perror("send failed");
        return -1;
    }

    // 接收响应
    ssize_t bytes_received;
    while ((bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0)) > 0) {
        buffer[bytes_received] = '\0';
        printf("%s", buffer);
    }

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

    return 0;
}

代码说明

  1. 创建套接字:使用 socket 函数创建一个 TCP 套接字。
  2. 设置服务器地址:设置服务器的 IP 地址和端口号。
  3. 连接到服务器:使用 connect 函数连接到服务器。
  4. 构建 HTTP 请求:构建一个简单的 HTTP GET 请求。
  5. 发送请求:使用 send 函数发送请求。
  6. 接收响应:使用 recv 函数接收服务器的响应。
  7. 关闭套接字:使用 close 函数关闭套接字。

HTTPS 通信例程

HTTPS 是基于 HTTP 的安全传输协议,需要使用 SSL/TLS 进行加密。在 C 语言中可以使用 OpenSSL 库来实现 HTTPS 通信。以下是一个示例代码,用于向指定的 HTTPS 服务器发送 GET 请求并接收响应:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#define BUFFER_SIZE 1024

void init_openssl() {
    SSL_load_error_strings();
    OpenSSL_add_ssl_algorithms();
}

void cleanup_openssl() {
    EVP_cleanup();
    ERR_free_strings();
}

SSL_CTX *create_context() {
    const SSL_METHOD *method;
    SSL_CTX *ctx;

    method = SSLv23_client_method();
    ctx = SSL_CTX_new(method);
    if (!ctx) {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    return ctx;
}

void configure_context(SSL_CTX *ctx) {
    SSL_CTX_set_ecdh_auto(ctx, 1);

    // 验证服务器证书
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
    if (SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs") != 1) {
        ERR_print_errors_fp(stderr);
    }
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];
    char request[BUFFER_SIZE];
    SSL_CTX *ctx;
    SSL *ssl;

    // 初始化 OpenSSL
    init_openssl();

    // 创建 SSL 上下文
    ctx = create_context();
    if (!ctx) {
        cleanup_openssl();
        return -1;
    }

    // 配置 SSL 上下文
    configure_context(ctx);

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(443); // HTTPS 默认端口
    if (inet_pton(AF_INET, "www.example.com", &server_addr.sin_addr) <= 0) {
        perror("invalid address or address not supported");
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connection failed");
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 创建 SSL 连接
    ssl = SSL_new(ctx);
    if (!ssl) {
        perror("unable to create SSL connection");
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 将 SSL 连接与套接字关联
    if (SSL_set_fd(ssl, sockfd) != 1) {
        perror("unable to set SSL fd");
        SSL_free(ssl);
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 执行 SSL 握手
    if (SSL_connect(ssl) != 1) {
        ERR_print_errors_fp(stderr);
        SSL_free(ssl);
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 构建 HTTP 请求
    snprintf(request, sizeof(request), "GET / HTTP/1.1\r\n"
                                       "Host: www.example.com\r\n"
                                       "Connection: close\r\n\r\n");

    // 发送请求
    if (SSL_write(ssl, request, strlen(request)) <= 0) {
        ERR_print_errors_fp(stderr);
        SSL_free(ssl);
        close(sockfd);
        SSL_CTX_free(ctx);
        cleanup_openssl();
        return -1;
    }

    // 接收响应
    ssize_t bytes_received;
    while ((bytes_received = SSL_read(ssl, buffer, sizeof(buffer) - 1)) > 0) {
        buffer[bytes_received] = '\0';
        printf("%s", buffer);
    }

    // 关闭 SSL 连接
    SSL_shutdown(ssl);
    SSL_free(ssl);

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

    // 清理 OpenSSL
    SSL_CTX_free(ctx);
    cleanup_openssl();

    return 0;
}

代码说明

  1. 初始化 OpenSSL:调用 init_openssl 函数初始化 OpenSSL 库。
  2. 创建 SSL 上下文:调用 create_context 函数创建 SSL 上下文。
  3. 配置 SSL 上下文:调用 configure_context 函数配置 SSL 上下文,包括验证服务器证书。
  4. 创建套接字:使用 socket 函数创建一个 TCP 套接字。
  5. 设置服务器地址:设置服务器的 IP 地址和端口号。
  6. 连接到服务器:使用 connect 函数连接到服务器。
  7. 创建 SSL 连接:使用 SSL_new 函数创建 SSL 连接,并使用 SSL_set_fd 函数将 SSL 连接与套接字关联。
  8. 执行 SSL 握手:使用 SSL_connect 函数执行 SSL 握手。
  9. 构建 HTTP 请求:构建一个简单的 HTTP GET 请求。
  10. 发送请求:使用 SSL_write 函数发送请求。
  11. 接收响应:使用 SSL_read 函数接收服务器的响应。
  12. 关闭 SSL 连接:使用 SSL_shutdown 和 SSL_free 函数关闭 SSL 连接。
  13. 关闭套接字:使用 close 函数关闭套接字。
  14. 清理 OpenSSL:调用 cleanup_openssl 函数清理 OpenSSL 库。

编译和运行

HTTP 例程
gcc http_example.c -o http_example
./http_example
HTTPS 例程
gcc https_example.c -o https_example -lssl -lcrypto
./https_example

以上代码仅是简单示例,实际应用中可能需要更多的错误处理和安全性检查。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值