[toc]

用C语言在windows中写http/https代理服务器

1.用C语言写一个tcp服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
一、服务器
0.初始化socket
1.创建socket
2.绑定地址与端口
3.监听
4.接受来自客户端的连接
5.接收消息->循环接收消息
6.关闭socket
*/
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#pragma comment(lib, "ws2_32.lib")

#define d_addr 127.0.0.1
#define d_port 8080

void Start();
int main(int argc,char**argv)
{
Start();
_getche();
return 0;
}
//0.初始化socket
void InitWSA()
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}
}
//1.创建socket
SOCKET CreateSocket()
{
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
return serverSocket;
}
//2.绑定地址与端口
void BindAddr(SOCKET serverSocket)
{
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; // 监听所有可用的接口
addr.sin_port = htons(d_port); // 服务器端口
int statue = bind(serverSocket, (struct sockaddr*)&addr,sizeof(addr));
if (statue == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(serverSocket);
WSACleanup();
return 1;
}
return;
}
//3.监听连接
void ListenSocket(SOCKET serverSocket)
{
listen(serverSocket, 3);
printf("Waiting for incoming connections...\n");
return;
}
//4.接受来自客户端的连接
SOCKET AcceptConnect(SOCKET serverSocket)
{
struct sockaddr_in clientAddr;
int clientSize = sizeof(clientAddr);
SOCKET clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientSize);
if (serverSocket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
char clientIP[INET_ADDRSTRLEN]; // 用于存储客户端 IP 地址
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, sizeof(clientIP)); // 使用 inet_ntop
printf("Connection accepted from %s:%d\n", clientIP, ntohs(clientAddr.sin_port));
return clientSocket;
}
//5.接收消息->循环接收消息
void ReciveMessage(SOCKET clientSocket)
{
char buffer[1024];
int recvSize;
// 接收消息
while ((recvSize = recv(clientSocket, buffer, sizeof(buffer) - 1, 0)) > 0) {
buffer[recvSize] = '\0'; // 添加字符串结束符
printf("Received message: %s\n", buffer);
}
if (recvSize == SOCKET_ERROR) {
printf("Receive failed. Error Code: %d\n", WSAGetLastError());
}
}
//6.关闭socket
void CloseSocket(SOCKET serverSocket, SOCKET clientSocket)
{
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return;
}
void Start()
{
InitWSA();
SOCKET serverSocket = CreateSocket();
BindAddr(serverSocket);
ListenSocket( serverSocket);
SOCKET clientSocket =AcceptConnect( serverSocket);
ReciveMessage( clientSocket);
CloseSocket(serverSocket, clientSocket);
return;
}

2.修改程序,修改为http服务器

  1. 创建一个html文件命名为index.html,存放在程序的当前目录
  2. 编写http_server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//http_server.c
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

int main()
{
//开启网络权限
WSAData wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_addr.S_un.S_addr = INADDR_ANY;
local.sin_port = htons(9090);

bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr));
listen(sock, 20);

int sockfd = accept(sock, NULL, NULL);

char buff[1024] = { 0 };
recv(sockfd, buff, 1024, 0);

printf("%s\n", buff);

FILE* fp = fopen("index.html", "rb+");
fseek(fp, 0, SEEK_END);
int FileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* FileCent = (char*)malloc(FileSize);
fread(FileCent, FileSize, 1, fp);
fclose(fp);

char HttpHead[512] = { 0 };
sprintf(HttpHead, "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nTransfer-Encoding: chunked\r\nConnection: Keep-Alive\r\nAccept-Ranges:bytes\r\nContent-Length:%d\r\n\r\n", FileSize);

send(sockfd, HttpHead, strlen(HttpHead), 0);
send(sockfd, FileCent, FileSize, 0);

closesocket(sockfd);
closesocket(sock);

return 0;
}

3.C语言在windows中写一个http代理服务器

1.http.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//http.c
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

#pragma comment(lib, "Ws2_32.lib") // 链接 Winsock 库

#define BUFFER_SIZE 4096

// 处理客户端请求的函数
DWORD WINAPI handle_client(void* arg) {
SOCKET client_sock = *((SOCKET*)arg);
free(arg); // 释放内存
char buffer[BUFFER_SIZE];
char method[16], url[256], protocol[16];
char host[128], path[256];
SOCKET server_sock;
struct addrinfo hints, * result;

while (1) {
// 接收客户端请求
int received = recv(client_sock, buffer, BUFFER_SIZE - 1, 0);
if (received <= 0) {
printf("Client disconnected or error occurred\n");
break;
}
buffer[received] = '\0';

// 解析 HTTP 请求行
if (sscanf(buffer, "%s %s %s", method, url, protocol) != 3) {
fprintf(stderr, "Invalid request: %s\n", buffer);
break;
}

// 检查是否为 GET 方法
if (strcmp(method, "GET") != 0) {
fprintf(stderr, "Only GET method is supported\n");
break;
}

// 提取主机名和路径
if (sscanf(url, "http://%[^/]%s", host, path) != 2) {
strcpy(path, "/"); // 如果路径为空,则设置为根路径
}

// 设置地址信息
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(host, "80", &hints, &result) != 0) {
fprintf(stderr, "Failed to resolve host: %s\n", host);
break;
}

// 创建服务器 socket
server_sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (server_sock == INVALID_SOCKET) {
perror("Failed to create server socket");
freeaddrinfo(result);
break;
}

// 连接目标服务器
if (connect(server_sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
perror("Failed to connect to server");
freeaddrinfo(result);
closesocket(server_sock);
break;
}
freeaddrinfo(result);

// 构建并发送代理的 HTTP 请求
snprintf(buffer, BUFFER_SIZE,
"GET %s %s\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"User-Agent: ProxyServer/1.0\r\n\r\n",
path, protocol, host);

if (send(server_sock, buffer, strlen(buffer), 0) == SOCKET_ERROR) {
perror("Failed to send request to server");
closesocket(server_sock);
break;
}

// 转发服务器响应给客户端
while ((received = recv(server_sock, buffer, BUFFER_SIZE, 0)) > 0) {
if (send(client_sock, buffer, received, 0) == SOCKET_ERROR) {
perror("Failed to send data to client");
break;
}
}

if (received < 0) {
perror("Error receiving data from server");
}

closesocket(server_sock); // 关闭服务器连接
}

closesocket(client_sock); // 关闭客户端连接
return 0;
}

int main(int argc, char* argv[]) {
WSADATA wsaData;
SOCKET proxy_sock, client_sock;
struct sockaddr_in proxy_addr, client_addr;
int client_len;

if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
return 1;
}

int port = atoi(argv[1]);

// 初始化 Winsock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
fprintf(stderr, "Failed to initialize Winsock\n");
return 1;
}

// 创建代理服务器 socket
proxy_sock = socket(AF_INET, SOCK_STREAM, 0);
if (proxy_sock == INVALID_SOCKET) {
perror("Failed to create proxy socket");
WSACleanup();
return 1;
}

// 配置代理地址
memset(&proxy_addr, 0, sizeof(proxy_addr));
proxy_addr.sin_family = AF_INET;
proxy_addr.sin_addr.s_addr = INADDR_ANY;
proxy_addr.sin_port = htons(port);

// 绑定并监听
if (bind(proxy_sock, (struct sockaddr*)&proxy_addr, sizeof(proxy_addr)) == SOCKET_ERROR) {
perror("Failed to bind proxy socket");
closesocket(proxy_sock);
WSACleanup();
return 1;
}

if (listen(proxy_sock, 10) == SOCKET_ERROR) {
perror("Failed to listen on proxy socket");
closesocket(proxy_sock);
WSACleanup();
return 1;
}

printf("Proxy server is running on port %d...\n", port);

// 接受并处理客户端请求
while (1) {
client_len = sizeof(client_addr);
client_sock = accept(proxy_sock, (struct sockaddr*)&client_addr, &client_len);
if (client_sock == INVALID_SOCKET) {
perror("Failed to accept client connection");
continue;
}

// 为每个客户端连接创建一个新的线程
HANDLE client_thread;
SOCKET* client_sock_ptr = malloc(sizeof(SOCKET));
*client_sock_ptr = client_sock;

client_thread = CreateThread(NULL, 0, handle_client, client_sock_ptr, 0, NULL);
if (client_thread == NULL) {
perror("Failed to create thread");
closesocket(client_sock);
free(client_sock_ptr);
}
else {
CloseHandle(client_thread); // 关闭线程句柄,线程自动清理
}
}

// 关闭代理服务器
closesocket(proxy_sock);
WSACleanup();
return 0;
}

2. 运行结果

  1. 在服务器中运行http.exe,此时服务器ip为10.0.4.1

    1
    .\http.exe 8080
  2. 在本机中设置http代理10.0.4.1:8080。

  3. 运行成功

4.C语言在windows中写一个https代理服务器

1.https.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
//https.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>

#define BUF_SIZE 8192
#define LISTEN_PORT 8080
#define INET_ADDRSTRLEN 16 // Windows 没有定义这个常量,我们手动定义

#pragma comment(lib, "ws2_32.lib") // 链接 Winsock 库

// 初始化 Winsock
int init_winsock() {
WSADATA wsaData;
return WSAStartup(MAKEWORD(2, 2), &wsaData);
}

// 解析 HTTP 请求头,获取目标主机和端口
int parse_http_request(SOCKET client_sock, char* host, int* port, int* is_https) {
char buffer[BUF_SIZE];
int total_len = 0;
int len = 0;

// 循环读取客户端发送的完整 HTTP 请求
while ((len = recv(client_sock, buffer + total_len, sizeof(buffer) - total_len - 1, 0)) > 0) {
total_len += len;
buffer[total_len] = '\0'; // 确保字符串终止符

printf("Received %d bytes, total length = %d\n", len, total_len);
printf("Partial Request:\n%s\n", buffer);


// 判断是否读取完整的请求头(以 "\r\n\r\n" 结束)
if (strstr(buffer, "\r\n\r\n") != NULL) {
break;
}
}

if (len <= 0) {
fprintf(stderr, "Failed to read HTTP request from client\n");
closesocket(client_sock);
return;
}

// 输出完整的 HTTP 请求
printf("Full HTTP Request:\n%s\n", buffer);

// 判断是否为 HTTPS 请求(CONNECT 请求)
if (strncmp(buffer, "CONNECT", 7) == 0) {
*is_https = 1;
char* start = buffer + 8;
char* end = strchr(start, ' ');
if (!end) return -1;

*end = '\0';
char* colon = strchr(start, ':');
if (colon) {
*colon = '\0';
strcpy_s(host, strlen(host)+1, start); // 使用 strcpy_s 防止溢出
*port = atoi(colon + 1);
}
else {
strcpy_s(host, strlen(host)+1, start); // 使用 strcpy_s 防止溢出
*port = 443; // 默认 HTTPS 端口
}
}
else
{
*is_https = 0;
const char* Errorinfo = " 400 Not Support\r";
printf("%s\n", Errorinfo);
return 0;
}

return 0;
}
// 定义一个结构体,用来存储 socket
typedef struct {
SOCKET client_sock;
SOCKET remote_sock;
} SocketPair;

// 数据转发函数
void forward_data(SocketPair* sockets) {
SOCKET src_sock = sockets->client_sock;
SOCKET dst_sock = sockets->remote_sock;
char buffer[BUF_SIZE];
int n;

while ((n = recv(src_sock, buffer, BUF_SIZE, 0)) > 0) {
printf("Forwarding %d bytes from source to destination\n", n); // 调试信息
if (send(dst_sock, buffer, n, 0) <= 0) {
perror("Forwarding error");
break;
}
}
}



// 处理客户端连接
void handle_client(SOCKET client_sock) {
char host[256];
int port;
int is_https = 0;

if (parse_http_request(client_sock, host, &port, &is_https) < 0) {
fprintf(stderr, "Failed to parse request\n");
closesocket(client_sock);
return;
}
if (!is_https)return;
printf("Connecting to %s:%d\n", host, port);

// 建立与目标服务器的连接
SOCKET remote_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (remote_sock == INVALID_SOCKET) {
perror("Socket creation failed");
closesocket(client_sock);
return;
}

struct sockaddr_in remote_addr;
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(port);

struct hostent* server = gethostbyname(host);
if (!server) {
fprintf(stderr, "No such host: %s\n", host);
closesocket(client_sock);
closesocket(remote_sock);
return;
}
memcpy(&remote_addr.sin_addr.s_addr, server->h_addr, server->h_length);

if (connect(remote_sock, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) == SOCKET_ERROR) {
perror("Failed to connect to remote server");
closesocket(client_sock);
closesocket(remote_sock);
return;
}

if (is_https) {
// 发送 HTTP 200 响应,表示隧道已建立
const char* tunnel_established = "HTTP/1.1 200 Connection Established\r\n\r\n";
send(client_sock, tunnel_established, strlen(tunnel_established), 0);
printf("Tunnel established for HTTPS\n");
}

// 创建 SocketPair 结构体,并传递给线程
SocketPair sockets1 = { client_sock, remote_sock };
SocketPair sockets2 = { remote_sock, client_sock };

// 创建线程并传递 SocketPair 结构体指针
HANDLE thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)forward_data, &sockets1, 0, NULL);
HANDLE thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)forward_data, &sockets2, 0, NULL);

// 等待线程完成
if (thread1 != NULL) {
WaitForSingleObject(thread1, INFINITE);
CloseHandle(thread1);
}
if (thread2 != NULL) {
WaitForSingleObject(thread2, INFINITE);
CloseHandle(thread2);
}

// 关闭连接
closesocket(client_sock);
closesocket(remote_sock);
}


// 服务器主程序
int main() {
if (init_winsock() != 0) {
fprintf(stderr, "Winsock initialization failed\n");
return 1;
}

SOCKET server_sock;
struct sockaddr_in server_addr, client_addr;
int client_len = sizeof(client_addr);

// 创建服务器 socket
server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_sock == INVALID_SOCKET) {
perror("Socket creation failed");
WSACleanup();
return 1;
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(LISTEN_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;

// 绑定端口
if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
perror("Bind failed");
closesocket(server_sock);
WSACleanup();
return 1;
}

if (listen(server_sock, 10) == SOCKET_ERROR) {
perror("Listen failed");
closesocket(server_sock);
WSACleanup();
return 1;
}

printf("Proxy server listening on port %d...\n", LISTEN_PORT);

while (1) {
SOCKET client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len);
if (client_sock == INVALID_SOCKET) {
perror("Accept failed");
continue;
}

// 使用 WSAAddressToString 来替代 InetNtop
char ip_str[INET_ADDRSTRLEN];
DWORD ip_str_len = INET_ADDRSTRLEN;
if (WSAAddressToString((struct sockaddr*)&client_addr, sizeof(client_addr), NULL, ip_str, &ip_str_len) == SOCKET_ERROR) {
fprintf(stderr, "Failed to convert IP address: %d\n", WSAGetLastError());
closesocket(client_sock);
continue;
}

printf("Accepted connection from %s:%d\n", ip_str, ntohs(client_addr.sin_port));

// 为每个客户端连接创建新的线程
HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handle_client, (LPVOID)client_sock, 0, NULL);
if (thread == NULL) {
fprintf(stderr, "Failed to create thread: %d\n", GetLastError());
closesocket(client_sock);
}
}

closesocket(server_sock);
WSACleanup();
return 0;
}

2. 运行结果

  1. 在服务器中运行https.exe,此时服务器ip为10.0.4.1
  2. 在本机中设置https代理10.0.4.1:8080
  3. 运行成功

5 .使用C语言在windows平台中写一个代理服务器,同时支持http/https协议

cproxy.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
//cproxy.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>

#define BUF_SIZE 8192
#define LISTEN_PORT 8080
#define INET_ADDRSTRLEN 16 // Windows 没有定义这个常量,我们手动定义

#pragma comment(lib, "Ws2_32.lib") // 链接 Winsock 库

// 初始化 Winsock
int init_winsock() {
WSADATA wsaData;
return WSAStartup(MAKEWORD(2, 2), &wsaData);
}

// 定义一个结构体,用来存储 socket
typedef struct {
SOCKET client_sock;
SOCKET remote_sock;
} SocketPair;

// 数据转发函数
DWORD WINAPI forward_data(void* arg) {
SocketPair* sockets = (SocketPair*)arg;
SOCKET src_sock = sockets->client_sock;
SOCKET dst_sock = sockets->remote_sock;
char buffer[BUF_SIZE];
int n;

while ((n = recv(src_sock, buffer, BUF_SIZE, 0)) > 0) {
if (send(dst_sock, buffer, n, 0) <= 0) {
perror("Forwarding error");
break;
}
}
free(sockets);
return 0;
}

// 解析 HTTP 请求头,获取目标主机和端口
int parse_http_request(SOCKET client_sock, char* host, int* port, int* is_https, char* path) {
char buffer[BUF_SIZE];
int total_len = 0;
int len;

while ((len = recv(client_sock, buffer + total_len, sizeof(buffer) - total_len - 1, 0)) > 0) {
total_len += len;
buffer[total_len] = '\0';

if (strstr(buffer, "\r\n\r\n") != NULL) {
break;
}
}

if (len <= 0) {
return -1;
}

if (strncmp(buffer, "CONNECT", 7) == 0) {
*is_https = 1;
sscanf_s(buffer, "CONNECT %[^:]:%d", host, (unsigned)_countof(host), port);

}
else {
*is_https = 0;
sscanf_s(buffer, "CONNECT %[^:]:%d", host, (unsigned)_countof(host), path);
*port = 80;
}
return 0;
}

// 处理客户端连接
void handle_client(SOCKET client_sock) {
char host[256];
int port;
int is_https = 0;
char path[256] = "/";

if (parse_http_request(client_sock, host, &port, &is_https, path) < 0) {
fprintf(stderr, "Failed to parse request\n");
closesocket(client_sock);
return;
}

printf("Connecting to %s:%d\n", host, port);

SOCKET remote_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (remote_sock == INVALID_SOCKET) {
perror("Socket creation failed");
closesocket(client_sock);
return;
}

struct addrinfo hints, * result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if (getaddrinfo(host, is_https ? "443" : "80", &hints, &result) != 0) {
fprintf(stderr, "Failed to resolve host: %s\n", host);
closesocket(client_sock);
closesocket(remote_sock);
return;
}

if (connect(remote_sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
perror("Failed to connect to remote server");
freeaddrinfo(result);
closesocket(client_sock);
closesocket(remote_sock);
return;
}
freeaddrinfo(result);

if (is_https) {
const char* response = "HTTP/1.1 200 Connection Established\r\n\r\n";
send(client_sock, response, strlen(response), 0);
}
else {
char request[BUF_SIZE];
snprintf(request, BUF_SIZE,
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n\r\n",
path, host);
send(remote_sock, request, strlen(request), 0);
}

SocketPair* sockets1 = malloc(sizeof(SocketPair));
SocketPair* sockets2 = malloc(sizeof(SocketPair));

sockets1->client_sock = client_sock;
sockets1->remote_sock = remote_sock;
sockets2->client_sock = remote_sock;
sockets2->remote_sock = client_sock;

HANDLE thread1 = CreateThread(NULL, 0, forward_data, sockets1, 0, NULL);
HANDLE thread2 = CreateThread(NULL, 0, forward_data, sockets2, 0, NULL);

WaitForSingleObject(thread1, INFINITE);
WaitForSingleObject(thread2, INFINITE);

CloseHandle(thread1);
CloseHandle(thread2);
closesocket(client_sock);
closesocket(remote_sock);
}

// 服务器主程序
int main() {
if (init_winsock() != 0) {
fprintf(stderr, "Winsock initialization failed\n");
return 1;
}

SOCKET server_sock;
struct sockaddr_in server_addr, client_addr;
int client_len = sizeof(client_addr);

server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_sock == INVALID_SOCKET) {
perror("Socket creation failed");
WSACleanup();
return 1;
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(LISTEN_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;

if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
perror("Bind failed");
closesocket(server_sock);
WSACleanup();
return 1;
}

if (listen(server_sock, 10) == SOCKET_ERROR) {
perror("Listen failed");
closesocket(server_sock);
WSACleanup();
return 1;
}

printf("Proxy server listening on port %d...\n", LISTEN_PORT);

while (1) {
SOCKET client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len);
if (client_sock == INVALID_SOCKET) {
perror("Accept failed");
continue;
}

HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)handle_client, (LPVOID)client_sock, 0, NULL);
if (thread == NULL) {
fprintf(stderr, "Failed to create thread\n");
closesocket(client_sock);
}
else {
CloseHandle(thread);
}
}

closesocket(server_sock);
WSACleanup();
return 0;
}

C语言在Linux中写http代理服务器

1.用C语言在Linux中写http代理服务器

访问http://info.cern.ch

其他的一些http网站

1
2
http://www.auiou.com/relevant/00000909.jsp
http://www.moe.gov.cn/

Linuxhttp.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
#include <netinet/in.h>
#include <signal.h>

#define BUFFER_SIZE 4096
#define TIMEOUT_SECONDS 5 // 设置超时为5秒

// 处理客户端请求
void* handle_client(void* arg) {
int client_sock = *((int*)arg);
free(arg); // 释放内存
char buffer[BUFFER_SIZE];
char method[16], url[256], protocol[16];
char host[128], path[256];
int server_sock;
struct sockaddr_in server_addr;

// 设置信号处理,捕获 SIGPIPE
signal(SIGPIPE, SIG_IGN);

while (1) { // 循环处理客户端请求
// 接收客户端请求
int received = recv(client_sock, buffer, BUFFER_SIZE - 1, 0);
if (received < 0) {
perror("Failed to receive data from client");
break; // 如果接收失败,退出循环
}
if (received == 0) {
printf("Client closed connection\n");
break; // 客户端关闭连接,跳出循环
}

buffer[received] = '\0';

// 解析 HTTP 请求行
if (sscanf(buffer, "%s %s %s", method, url, protocol) != 3) {
fprintf(stderr, "Invalid request: %s\n", buffer);
break;
}

// 检查是否为 GET 方法
if (strcmp(method, "GET") != 0) {
fprintf(stderr, "Only GET method is supported\n");
break;
}

// 提取主机名和路径
if (sscanf(url, "http://%[^/]%s", host, path) != 2) {
strcpy(path, "/"); // 如果路径为空,则设置为根路径
}

// 创建连接到目标服务器的 socket
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) {
perror("Failed to create socket to server");
break; // 如果无法创建 socket,退出循环
}

// 解析目标主机 IP
struct hostent* server = gethostbyname(host);
if (!server) {
fprintf(stderr, "No such host: %s\n", host);
break; // 如果无法解析主机名,退出循环
}

memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(80);
memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);

// 连接到目标服务器
if (connect(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Failed to connect to server");
break; // 如果连接失败,退出循环
}

// 构建并发送代理的 HTTP 请求
snprintf(buffer, BUFFER_SIZE,
"GET %s %s\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"User-Agent: ProxyServer/1.0\r\n\r\n",
path, protocol, host);

if (send(server_sock, buffer, strlen(buffer), 0) < 0) {
perror("Failed to send request to server");
break; // 如果发送请求失败,退出循环
}

// 转发服务器响应给客户端
while ((received = recv(server_sock, buffer, BUFFER_SIZE, 0)) > 0) {
if (send(client_sock, buffer, received, 0) < 0) {
perror("Failed to send data to client");
break; // 如果发送数据失败,退出循环
}
}

if (received < 0) {
perror("Error receiving data from server");
}

// 关闭服务器连接
close(server_sock);
}

// 关闭客户端连接
close(client_sock);
return NULL;
}

int main(int argc, char* argv[]) {
int proxy_sock, client_sock;
struct sockaddr_in proxy_addr, client_addr;
socklen_t client_len;

if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
return 1;
}

int port = atoi(argv[1]);

// 创建代理服务器 socket
proxy_sock = socket(AF_INET, SOCK_STREAM, 0);
if (proxy_sock < 0) {
perror("Failed to create proxy socket");
return 1;
}

memset(&proxy_addr, 0, sizeof(proxy_addr));
proxy_addr.sin_family = AF_INET;
proxy_addr.sin_addr.s_addr = INADDR_ANY;
proxy_addr.sin_port = htons(port);

// 绑定并监听
if (bind(proxy_sock, (struct sockaddr*)&proxy_addr, sizeof(proxy_addr)) < 0) {
perror("Failed to bind proxy socket");
close(proxy_sock);
return 1;
}

if (listen(proxy_sock, 10) < 0) {
perror("Failed to listen on proxy socket");
close(proxy_sock);
return 1;
}

printf("Proxy server is running on port %d...\n", port);

// 接受并处理客户端请求
while ((client_sock = accept(proxy_sock, (struct sockaddr*)&client_addr, &client_len)) >= 0) {
// 为每个客户端连接创建一个新的线程
pthread_t client_thread;
int* client_sock_ptr = malloc(sizeof(int));
*client_sock_ptr = client_sock;
if (pthread_create(&client_thread, NULL, handle_client, client_sock_ptr) != 0) {
perror("Failed to create thread");
close(client_sock);
} else {
// Detach thread so it cleans up after itself
pthread_detach(client_thread);
}
}

// 关闭代理服务器
close(proxy_sock);
return 0;
}

2.用C语言在Linux中写https代理服务器

linuxhttps.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//linuxhttps.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netdb.h> // 解决 gethostbyname 和 struct hostent 的定义问题


#define BUF_SIZE 8192
#define LISTEN_PORT 8080

// 读取 HTTP 请求头,获取目标主机和端口
int parse_http_request(int client_sock, char *host, int *port, int *is_https) {
char buffer[BUF_SIZE];
int len = recv(client_sock, buffer, sizeof(buffer) - 1, 0);
if (len <= 0) return -1;

buffer[len] = '\0';
printf("Received Request:\n%s", buffer);

if (strncmp(buffer, "CONNECT", 7) == 0) { // HTTPS 隧道请求
*is_https = 1;
char *start = buffer + 8;
char *end = strchr(start, ' ');
if (!end) return -1;

*end = '\0';
char *colon = strchr(start, ':');
if (colon) {
*colon = '\0';
strcpy(host, start);
*port = atoi(colon + 1);
} else {
strcpy(host, start);
*port = 443; // 默认 HTTPS 端口
}
} else { // 其他 请求
*is_https = 0;
const char* Errorinfo = " 400 Not Support\r";
printf("%s\n", Errorinfo);
return 0;

}

return 0;
}

// 数据转发函数
void forward_data(int src_sock, int dst_sock) {
char buffer[BUF_SIZE];
ssize_t n;

while ((n = recv(src_sock, buffer, BUF_SIZE, 0)) > 0) {
if (send(dst_sock, buffer, n, 0) <= 0) {
perror("Forwarding error");
break;
}
}
}

// 处理客户端连接
void handle_client(int client_sock) {
char host[256];
int port;
int is_https = 0;

if (parse_http_request(client_sock, host, &port, &is_https) < 0) {
fprintf(stderr, "Failed to parse request\n");
close(client_sock);
return;
}

if (!is_https)return;
printf("Connecting to %s:%d\n", host, port);

// 建立与目标服务器的连接
int remote_sock = socket(AF_INET, SOCK_STREAM, 0);
if (remote_sock < 0) {
perror("Socket creation failed");
close(client_sock);
return;
}

struct sockaddr_in remote_addr;
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(port);

struct hostent *server = gethostbyname(host);
if (!server) {
fprintf(stderr, "No such host: %s\n", host);
close(client_sock);
close(remote_sock);
return;
}
memcpy(&remote_addr.sin_addr.s_addr, server->h_addr, server->h_length);

if (connect(remote_sock, (struct sockaddr *)&remote_addr, sizeof(remote_addr)) < 0) {
perror("Failed to connect to remote server");
close(client_sock);
close(remote_sock);
return;
}

if (is_https) {
// 发送 HTTP 200 响应,表示隧道已建立
const char *tunnel_established = "HTTP/1.1 200 Connection Established\r\n\r\n";
send(client_sock, tunnel_established, strlen(tunnel_established), 0);
}

// 数据转发,分别处理两个方向
if (fork() == 0) {
forward_data(client_sock, remote_sock); // 客户端 -> 目标服务器
exit(0);
}
if (fork() == 0) {
forward_data(remote_sock, client_sock); // 目标服务器 -> 客户端
exit(0);
}

close(client_sock);
close(remote_sock);
wait(NULL);
wait(NULL);
}

int main() {
int server_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);

// 创建服务器 socket
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) {
perror("Socket creation failed");
exit(1);
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(LISTEN_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;

// 绑定端口
if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(server_sock);
exit(1);
}

if (listen(server_sock, 10) < 0) {
perror("Listen failed");
close(server_sock);
exit(1);
}

printf("Proxy server listening on port %d...\n", LISTEN_PORT);

while (1) {
int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len);
if (client_sock < 0) {
perror("Accept failed");
continue;
}

printf("Accepted connection from %s:%d\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

if (fork() == 0) { // 创建子进程处理客户端
close(server_sock);
handle_client(client_sock);
exit(0);
}
close(client_sock);
}

close(server_sock);
return 0;
}

3.使用C语言在Linux平台中写一个代理服务器,同时支持http/https协议

linux_cproxy.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
//linux_cproxy.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <netdb.h>

#define BUF_SIZE 8192
#define LISTEN_PORT 8080

typedef struct {
int client_sock;
int remote_sock;
} SocketPair;

// 在 forward_data 函数中确保释放内存
void* forward_data(void* arg) {
SocketPair* sockets = (SocketPair*)arg;
int src_sock = sockets->client_sock;
int dst_sock = sockets->remote_sock;
char buffer[BUF_SIZE];
int n;

while ((n = recv(src_sock, buffer, BUF_SIZE, 0)) > 0) {
if (send(dst_sock, buffer, n, 0) <= 0) {
perror("Forwarding error");
break;
}
}
close(src_sock); // 关闭源套接字
close(dst_sock); // 关闭目标套接字
free(sockets); // 释放内存
return NULL;
}

int parse_http_request(int client_sock, char* host, int* port, int* is_https, char* path) {
char buffer[BUF_SIZE];
int total_len = 0;
int len;

while ((len = recv(client_sock, buffer + total_len, sizeof(buffer) - total_len - 1, 0)) > 0) {
total_len += len;
buffer[total_len] = '\0';

if (strstr(buffer, "\r\n\r\n") != NULL) {
break;
}
}

if (len <= 0) {
return -1;
}

if (strncmp(buffer, "CONNECT", 7) == 0) {
*is_https = 1;
if (sscanf(buffer, "CONNECT %[^:]:%d", host, port) != 2) {
return -1; // 解析失败
}
} else {
*is_https = 0;
if (sscanf(buffer, "GET http://%[^/]%s", host, path) != 2) {
return -1; // 解析失败
}
*port = 80;
}
return 0;
}

void handle_client(int client_sock) {
char host[256];
int port;
int is_https = 0;
char path[256] = "/";

if (parse_http_request(client_sock, host, &port, &is_https, path) < 0) {
fprintf(stderr, "Failed to parse request\n");
close(client_sock);
return;
}

printf("Connecting to %s:%d\n", host, port);

int remote_sock = socket(AF_INET, SOCK_STREAM, 0);
if (remote_sock < 0) {
perror("Socket creation failed");
close(client_sock);
return;
}

struct addrinfo hints, *result;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if (getaddrinfo(host, is_https ? "443" : "80", &hints, &result) != 0) {
fprintf(stderr, "Failed to resolve host: %s\n", host);
close(client_sock);
close(remote_sock);
return;
}

if (connect(remote_sock, result->ai_addr, result->ai_addrlen) < 0) {
perror("Failed to connect to remote server");
freeaddrinfo(result);
close(client_sock);
close(remote_sock);
return;
}
freeaddrinfo(result);

if (is_https) {
const char* response = "HTTP/1.1 200 Connection Established\r\n\r\n";
send(client_sock, response, strlen(response), 0);
} else {
char request[BUF_SIZE];
snprintf(request, BUF_SIZE,
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n\r\n",
path, host);
send(remote_sock, request, strlen(request), 0);
}

SocketPair* sockets1 = malloc(sizeof(SocketPair));
SocketPair* sockets2 = malloc(sizeof(SocketPair));

if (sockets1 == NULL || sockets2 == NULL) {
perror("Failed to allocate memory for socket pairs");
close(client_sock);
close(remote_sock);
return;
}

sockets1->client_sock = client_sock;
sockets1->remote_sock = remote_sock;
sockets2->client_sock = remote_sock;
sockets2->remote_sock = client_sock;

pthread_t thread1, thread2;
if (pthread_create(&thread1, NULL, forward_data, sockets1) != 0) {
perror("Failed to create thread for forwarding data from client to remote");
free(sockets1);
free(sockets2);
close(client_sock);
close(remote_sock);
return;
}

if (pthread_create(&thread2, NULL, forward_data, sockets2) != 0) {
perror("Failed to create thread for forwarding data from remote to client");
free(sockets1);
free(sockets2);
close(client_sock);
close(remote_sock);
return;
}

pthread_detach(thread1);
pthread_detach(thread2);
}

// 服务器主程序
int main() {
int server_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr);

server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock < 0) {
perror("Socket creation failed");
return 1;
}

// 设置 SO_REUSEADDR 选项
int opt = 1;
if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt failed");
close(server_sock);
return 1;
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(LISTEN_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;

if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("Bind failed");
close(server_sock);
return 1;
}

if (listen(server_sock, 10) < 0) {
perror("Listen failed");
close(server_sock);
return 1;
}

printf("Proxy server listening on port %d...\n", LISTEN_PORT);

while (1) {
int client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_len);
if (client_sock < 0) {
perror("Accept failed");
continue;
}

// 创建一个新线程来处理客户端连接
pthread_t thread;
if (pthread_create(&thread, NULL, (void* (*)(void*))handle_client, (void*)(intptr_t)client_sock) != 0) {
fprintf(stderr, "Failed to create thread\n");
close(client_sock);
} else {
pthread_detach(thread); // 使线程在结束时自动释放资源
}
}

close(server_sock);
return 0;
}