-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.cpp
More file actions
204 lines (176 loc) · 6.59 KB
/
server.cpp
File metadata and controls
204 lines (176 loc) · 6.59 KB
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
/**
* @file server.cpp
* @brief 简单的HTTP服务器 - 提供DLL文件下载
*
* 这是一个极简的HTTP服务器,用于向injector提供DLL文件下载服务。
* 编译命令: g++ -o server.exe server.cpp -lws2_32
*/
#include <winsock2.h> // Windows Sockets 2 API
#include <ws2tcpip.h> // TCP/IP相关函数
#include <windows.h> // Windows API
#include <fstream> // 文件输入输出
#include <iostream> // 标准输入输出
#include <cstring> // C字符串处理
#pragma comment(lib, "ws2_32.lib") // 链接WinSock库
// 服务器监听端口
#define PORT 8000
// 接收缓冲区大小 (4KB)
#define BUFFER_SIZE 4096
/**
* @brief 发送HTTP响应
*
* 构造并发送HTTP响应报文给客户端。
*
* @param client_socket 客户端连接套接字
* @param status HTTP状态码 (如 "200 OK", "404 Not Found")
* @param content_type 内容类型 (如 "text/plain", "application/octet-stream")
* @param body 响应体数据
* @param body_length 响应体长度
*/
void send_response(SOCKET client_socket, const char* status, const char* content_type, const void* body, int body_length) {
char header[BUFFER_SIZE];
// 构建HTTP响应头
// 格式: HTTP/1.1 Status\r\nHeader\r\n\r\nBody
sprintf(header,
"HTTP/1.1 %s\r\n" // 状态行
"Content-Type: %s\r\n" // 内容类型
"Content-Length: %d\r\n" // 内容长度
"Connection: close\r\n" // 关闭连接
"\r\n", // 头部结束标记
status, content_type, body_length);
// 发送HTTP头部
send(client_socket, header, strlen(header), 0);
// 如果有响应体,发送响应体
if (body && body_length > 0) {
send(client_socket, (const char*)body, body_length, 0);
}
}
/**
* @brief 发送文件给客户端
*
* 读取本地文件并通过HTTP响应发送给客户端。
*
* @param client_socket 客户端连接套接字
* @param filepath 要发送的文件路径
*/
void send_file(SOCKET client_socket, const char* filepath) {
// 以二进制模式打开文件,'ate'表示定位到文件末尾以便获取大小
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
// 检查文件是否成功打开
if (!file.is_open()) {
// 文件不存在,返回404
const char* not_found = "404 Not Found";
send_response(client_socket, "404 Not Found", "text/plain", not_found, strlen(not_found));
return;
}
// 获取文件大小 (tellg返回当前指针位置,即文件末尾位置=文件大小)
int file_size = file.tellg();
// 重新定位到文件开始
file.seekg(0, std::ios::beg);
// 分配缓冲区并读取文件内容
char* buffer = new char[file_size];
file.read(buffer, file_size);
// 关闭文件句柄
file.close();
// 发送文件内容,使用application/octet-stream表示二进制流
send_response(client_socket, "200 OK", "application/octet-stream", buffer, file_size);
// 释放缓冲区
delete[] buffer;
}
/**
* @brief 处理客户端HTTP请求
*
* 解析HTTP请求并返回相应内容。
* 支持:
* - GET /a.dll - 下载DLL文件
* - GET / - 服务器状态
*
* @param client_socket 客户端连接套接字
*/
void handle_client(SOCKET client_socket) {
// 接收缓冲区
char buffer[BUFFER_SIZE];
// 初始化缓冲区为零
memset(buffer, 0, BUFFER_SIZE);
// 接收客户端发送的HTTP请求
int bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
// 如果接收失败或连接关闭
if (bytes_received <= 0) {
closesocket(client_socket);
return;
}
// 将缓冲区转换为string便于处理
std::string request(buffer);
// 根据请求路径判断返回内容
if (request.find("GET /a.dll") != std::string::npos) {
// 请求下载DLL文件
send_file(client_socket, "a.dll");
} else if (request.find("GET /") != std::string::npos) {
// 根路径请求,返回服务器状态
const char* msg = "DLL Download Server Running";
send_response(client_socket, "200 OK", "text/plain", msg, strlen(msg));
} else {
// 其他路径,返回404
const char* not_found = "404 Not Found";
send_response(client_socket, "404 Not Found", "text/plain", not_found, strlen(not_found));
}
// 关闭与客户端的连接
closesocket(client_socket);
}
/**
* @brief 主函数 - HTTP服务器入口
*
* 初始化WinSock,创建监听套接字,接受客户端连接并处理请求。
*/
int main() {
// WSADATA结构体,用于存储Winsock初始化信息
WSADATA wsa_data;
// 初始化Winsock库 (版本2.2)
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) {
std::cerr << "WSAStartup failed" << std::endl;
return 1;
}
// 创建TCP套接字 (IPv4, 流式套接字, TCP协议)
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
std::cerr << "Socket creation failed" << std::endl;
WSACleanup();
return 1;
}
// 设置服务器地址结构
sockaddr_in server_addr;
server_addr.sin_family = AF_INET; // IPv4
server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡
server_addr.sin_port = htons(PORT); // 端口号 (网络字节序)
// 绑定套接字到指定地址和端口
if (bind(server_socket, (sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
std::cerr << "Bind failed" << std::endl;
closesocket(server_socket);
WSACleanup();
return 1;
}
// 开始监听连接请求 (SOMAXCONN = 使用系统最大连接数)
if (listen(server_socket, SOMAXCONN) == SOCKET_ERROR) {
std::cerr << "Listen failed" << std::endl;
closesocket(server_socket);
WSACleanup();
return 1;
}
// 服务器启动成功,显示信息
std::cout << "Server running on http://localhost:" << PORT << std::endl;
std::cout << "Download DLL: http://localhost:" << PORT << "/a.dll" << std::endl;
// 主循环:接受并处理客户端连接
while (true) {
// 接受客户端连接 (阻塞等待)
SOCKET client_socket = accept(server_socket, NULL, NULL);
if (client_socket == INVALID_SOCKET) {
continue; // 接受失败,继续等待
}
// 处理客户端请求
handle_client(client_socket);
}
// 程序正常情况下不会执行到这里
closesocket(server_socket);
WSACleanup();
return 0;
}