1、使用 libcurl(推荐)
使用 libcurl
实现 HTTP GET
和 POST
请求是一种非常推荐的做法,因为 libcurl
是一个功能强大、跨平台的网络传输库,支持 HTTP
、HTTPS
、FTP 等多种协议。
1)GET 请求
#include <stdio.h>
#include <curl/curl.h>
// 回调函数,用于接收服务器响应数据
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
size_t total_size = size * nmemb;
fwrite(ptr, size, nmemb, stdout); // 打印响应内容到控制台
return total_size;
}
int main(void) {
CURL *curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/get");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
CURLcode res = curl_easy_perform(curl); // 执行请求
if (res != CURLE_OK) {
fprintf(stderr, "GET request failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl); // 清理资源
}
return 0;
}
2)POST 请求
#include <stdio.h>
#include <curl/curl.h>
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
size_t total_size = size * nmemb;
fwrite(ptr, size, nmemb, stdout);
return total_size;
}
int main(void) {
CURL *curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://httpbin.org/post");
curl_easy_setopt(curl, CURLOPT_POST, 1L);
// 设置 POST 数据
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=Levi&age=25");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "POST request failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
return 0;
}
2、使用 sockets + HTTP 手写协议
使用sockets更底层,要自己构建 HTTP 请求格式。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 8192
void send_request(const char *host, const char *port, const char *request) {
struct hostent *server = gethostbyname(host);
if (!server) {
fprintf(stderr, "ERROR: No such host\n");
exit(1);
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(port));
memcpy(&serv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
close(sockfd);
exit(1);
}
send(sockfd, request, strlen(request), 0);
char buffer[BUFFER_SIZE];
int bytes_received;
while ((bytes_received = recv(sockfd, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[bytes_received] = '\0';
printf("%s", buffer);
}
close(sockfd);
}
void http_get() {
const char *host = "httpbin.org";
const char *port = "80";
const char *path = "/get";
char request[512];
snprintf(request, sizeof(request),
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"\r\n",
path, host);
send_request(host, port, request);
}
void http_post() {
const char *host = "httpbin.org";
const char *port = "80";
const char *path = "/post";
const char *data = "name=Levi&age=30";
char request[1024];
snprintf(request, sizeof(request),
"POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %zu\r\n"
"Connection: close\r\n"
"\r\n"
"%s",
path, host, strlen(data), data);
send_request(host, port, request);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s get|post\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "get") == 0) {
http_get();
} else if (strcmp(argv[1], "post") == 0) {
http_post();
} else {
fprintf(stderr, "Unknown command: %s\n", argv[1]);
return 1;
}
return 0;
}