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_shutdownSSL_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

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

相关推荐
Tummer836334 分钟前
C语言与C++的区别
c语言·c++·算法
爱分享的程序员1 小时前
微信小程序执行C语言库的详细方案
c语言·微信小程序·小程序
又熟了2 小时前
WDG看门狗(独立看门狗和窗口看门狗)
c语言·stm32·单片机·嵌入式硬件
柒柒的代码学习日记6 小时前
数组和指针典型例题合集(一维数组、字符数组、二维数组)
c语言
大龄Python青年10 小时前
C语言 交换算法之加减法,及溢出防范
c语言·开发语言·算法
谷雪_65812 小时前
鼠标交互初体验:点击屏幕生成彩色气泡(EGE 库基础)
c语言·开发语言·microsoft·交互
喜欢吃燃面15 小时前
C++:扫雷游戏
c语言·c++·学习
小郝 小郝16 小时前
【C语言】五一回归,复习动脑
c语言·开发语言
天夏已微凉18 小时前
1.2 Linux音频系统发展历程与关键技术演进
linux·c语言·驱动开发·音视频
草莓熊Lotso19 小时前
【C语言】--指针超详解(二)
c语言·开发语言·经验分享·笔记