113 lines
2.8 KiB
C
113 lines
2.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
|
|
|
|
#define BUF_SIZE 4096
|
|
#define BODY_BUF 2048
|
|
|
|
// 域名转IP
|
|
static int domain_to_ip(const char *domain, char *ip_buf) {
|
|
struct hostent *host = gethostbyname(domain);
|
|
if (!host) return -1;
|
|
struct in_addr **addr_list = (struct in_addr **)host->h_addr_list;
|
|
strcpy(ip_buf, inet_ntoa(*addr_list[0]));
|
|
return 0;
|
|
}
|
|
|
|
// 从 HTTP 完整响应中提取正文(跳过头部)
|
|
void extract_http_body(const char *response, char *body) {
|
|
const char *split = "\r\n\r\n";
|
|
char *pos = strstr(response, split);
|
|
if (pos) {
|
|
strcpy(body, pos + 4); // 跳过 \r\n\r\n
|
|
} else {
|
|
strcpy(body, "parse error");
|
|
}
|
|
}
|
|
|
|
// HTTP GET,返回完整响应字符串
|
|
int http_get(const char *host, const char *path, int port, char *response) {
|
|
int sock;
|
|
struct sockaddr_in addr;
|
|
char ip[64], req[512];
|
|
int total_len = 0;
|
|
|
|
if (domain_to_ip(host, ip) < 0) return -1;
|
|
|
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = inet_addr(ip);
|
|
|
|
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
close(sock);
|
|
return -2;
|
|
}
|
|
|
|
snprintf(req, sizeof(req),
|
|
"GET %s HTTP/1.1\r\n"
|
|
"Host: %s\r\n"
|
|
"Connection: close\r\n\r\n",
|
|
path, host);
|
|
|
|
send(sock, req, strlen(req), 0);
|
|
|
|
// 接收完整数据
|
|
while (1) {
|
|
int len = recv(sock, response + total_len, BUF_SIZE - 1 - total_len, 0);
|
|
if (len <= 0) break;
|
|
total_len += len;
|
|
}
|
|
|
|
response[total_len] = 0;
|
|
close(sock);
|
|
return total_len;
|
|
}
|
|
|
|
// HTTP POST
|
|
int http_post(const char *host, const char *path, int port, const char *data, int data_len, char *response) {
|
|
int sock;
|
|
struct sockaddr_in addr;
|
|
char ip[64], req[1024];
|
|
int total_len = 0;
|
|
|
|
if (domain_to_ip(host, ip) < 0) return -1;
|
|
|
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = inet_addr(ip);
|
|
|
|
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
close(sock);
|
|
return -2;
|
|
}
|
|
|
|
snprintf(req, sizeof(req),
|
|
"POST %s HTTP/1.1\r\n"
|
|
"Host: %s\r\n"
|
|
"Content-Type: application/x-www-form-urlencoded\r\n"
|
|
"Content-Length: %d\r\n"
|
|
"Connection: close\r\n\r\n%s",
|
|
path, host, data_len, data);
|
|
|
|
send(sock, req, strlen(req), 0);
|
|
|
|
while (1) {
|
|
int len = recv(sock, response + total_len, BUF_SIZE - 1 - total_len, 0);
|
|
if (len <= 0) break;
|
|
total_len += len;
|
|
}
|
|
|
|
response[total_len] = 0;
|
|
close(sock);
|
|
return total_len;
|
|
}
|
|
|