[toc]

用C语言在windows中使用http协议浏览网页

1.用C语言在windows中使用http协议浏览静态网页

WinServer.c

这个服务器程序将能够处理GET请求,并返回一个简单的HTML页面。

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
//WinServer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
const char* response_body;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
if (strcmp(path, "/") == 0) {
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
response_body = "<html><body><h1>Welcome to the Home Page!</h1></body></html>";
}
else if (strcmp(path, "/hello") == 0) {
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
response_body = "<html><body><h1>Hello, World!</h1></body></html>";
}
else {
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
response_body = "<html><body><h1>404 Not Found</h1></body></html>";
}

// 发送响应
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, response_body, strlen(response_body), 0);
}
}

// 关闭客户端套接字
closesocket(client_socket);
}

int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

WInClient.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
//WInClient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define SERVER "127.0.0.1" // 服务器地址
#define PORT 8080 // 服务器端口
#define BUFFER_SIZE 1024

int main() {
WSADATA wsaData;
SOCKET sock;
struct sockaddr_in server;
char request[BUFFER_SIZE], response[BUFFER_SIZE];
int bytes_received;

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVER);
server.sin_port = htons(PORT);

// 连接到服务器
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Connect failed. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}

// 构建HTTP GET请求
sprintf(request, "GET /hello HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n\r\n", SERVER);

// 发送请求
send(sock, request, strlen(request), 0);

// 接收响应
while ((bytes_received = recv(sock, response, sizeof(response) - 1, 0)) > 0) {
response[bytes_received] = '\0'; // 添加字符串结束符
printf("%s", response); // 打印响应
}

// 关闭套接字
closesocket(sock);
WSACleanup();
return 0;
}

运行结果

  1. 运行WinServer.exe

  2. 运行WinClient.exe或浏览器中访问http://127.0.0.1:8080/First.html

  3. 运行成功

2.修改程序,让程序可以解析D盘根目录的First.html文件

First.html

在D盘根目录下创建一个名为First.html的文件,并添加一些HTML内容

1
2
3
4
5
6
<html>
<body>
<h1>This is First.html</h1>
<p>Welcome to the static HTML page served by the HTTP server!</p>
</body>
</html>

WinServer.c

这个服务器程序将能够处理GET请求,并返回D盘根目录下的First.html文件内容。

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
//WinServer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024
#define FILE_PATH "D:\\First.html" // 文件路径

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
char response_body[BUFFER_SIZE];
FILE* file;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
if (strcmp(path, "/First.html") == 0) {
// 打开文件并读取内容
file = fopen(FILE_PATH, "r");
if (file) {
// 读取文件内容
size_t bytes_read = fread(response_body, sizeof(char), sizeof(response_body) - 1, file);
response_body[bytes_read] = '\0'; // 确保字符串结束
fclose(file);

// 发送响应头
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %lu\r\n"
"Connection: close\r\n\r\n";
char header[BUFFER_SIZE];
sprintf(header, response_header, bytes_read);
send(client_socket, header, strlen(header), 0);
send(client_socket, response_body, bytes_read, 0);
}
else {
// 文件未找到
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
else {
// 处理其他路径
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
}

// 关闭客户端套接字
closesocket(client_socket);
}

int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

WinClient.c

这个客户端程序将请求服务器的First.html文件,并打印出服务器的响应。

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
//WinClient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <conio.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define SERVER "127.0.0.1" // 服务器地址
#define PORT 8080 // 服务器端口
#define BUFFER_SIZE 1024

int main() {
WSADATA wsaData;
SOCKET sock;
struct sockaddr_in server;
char request[BUFFER_SIZE], response[BUFFER_SIZE];
int bytes_received;

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVER);
server.sin_port = htons(PORT);

// 连接到服务器
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Connect failed. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}

// 构建HTTP GET请求
sprintf(request, "GET /First.html HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n\r\n", SERVER);

// 发送请求
send(sock, request, strlen(request), 0);

// 接收响应
while ((bytes_received = recv(sock, response, sizeof(response) - 1, 0)) > 0) {
response[bytes_received] = '\0'; // 添加字符串结束符
printf("%s", response); // 打印响应
}

// 关闭套接字
closesocket(sock);
WSACleanup();
getche();
return 0;
}

运行结果

  1. 在D盘根目录创建First.html

  2. 运行WinServer.exe

  3. 运行WinClient.exe或者浏览器中访问http://127.0.0.1:8080/First.html

  4. 运行成功

3.修改服务端程序,让程序可以访问多个html文件

WinSever.c

设置D盘根目录为基本路径,通过相对路径访问First.html

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024
#define BASE_PATH "D:\\" // 基础文件路径

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
char response_body[BUFFER_SIZE];
FILE* file;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
// 构建文件路径
char file_path[BUFFER_SIZE];
snprintf(file_path, sizeof(file_path), "%s%s", BASE_PATH, path + 1); // 路径前加上基础路径,去掉前面的'/'

// 打开文件并读取内容
file = fopen(file_path, "r");
if (file) {
// 读取文件内容
size_t bytes_read = fread(response_body, sizeof(char), sizeof(response_body) - 1, file);
response_body[bytes_read] = '\0'; // 确保字符串结束
fclose(file);

// 发送响应头
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %lu\r\n"
"Connection: close\r\n\r\n";
char header[BUFFER_SIZE];
sprintf(header, response_header, bytes_read);
send(client_socket, header, strlen(header), 0);
send(client_socket, response_body, bytes_read, 0);
}
else {
// 文件未找到
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
}

// 关闭客户端套接字
closesocket(client_socket);
}

int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

运行结果

  1. 在D盘根目录创建First.html
  2. 运行WinServer.exe
  3. 运行WinClient.exe或者浏览器中访问http://127.0.0.1:8080/First.html
  4. 运行成功

4. 修改程序,让程序可以解析css

1. 修改First.html

将First.html文件保存在”D:/First/First.html”中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>First</title>
<!-- 设置:h3{color:blue;} -->
<style type="text/css">
/* 内部样式 */
h3{color:green;}
</style>
</head>
<body>

<h3>显示绿色,是内部样式</h3>

</body>
</html>

2.修改WinServer.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024
#define BASE_PATH "D:\\" // 基础文件路径

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
char response_body[BUFFER_SIZE];
FILE* file;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
// 构建文件路径
char file_path[BUFFER_SIZE];
snprintf(file_path, sizeof(file_path), "%s%s", BASE_PATH, path + 1); // 路径前加上基础路径,去掉前面的'/'

// 打开文件并读取内容
file = fopen(file_path, "r");
if (file) {
// 读取文件内容
size_t bytes_read = fread(response_body, sizeof(char), sizeof(response_body) - 1, file);
response_body[bytes_read] = '\0'; // 确保字符串结束
fclose(file);

// 确定 Content-Type
const char* content_type;
if (strstr(path, ".html")) {
content_type = "text/html";
}
else if (strstr(path, ".css")) {
content_type = "text/css";
}
else {
content_type = "application/octet-stream"; // 默认类型
}

// 发送响应头
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %lu\r\n"
"Connection: close\r\n\r\n";
char header[BUFFER_SIZE];
sprintf(header, response_header, content_type, bytes_read);
send(client_socket, header, strlen(header), 0);
send(client_socket, response_body, bytes_read, 0);
}
else {
// 文件未找到
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
}

// 关闭客户端套接字
closesocket(client_socket);
}

int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

3. 运行结果

  1. 运行WinServer.exe
  2. 在浏览器中访问http://127.0.0.1:8080/First/First.html
  3. 运行成功

5. 修改程序,让程序可以解析javascript

1. 修改First.html

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>简单的JavaScript Hello World</title>
<script src="example.js"></script>
</head>
<body>
    HTML内容……
</body>
</html>

2.创建example.js

D:\First文件夹中创建example.js

1
2
3
4

document.write("Hello, world!"); // 直接插入页面中
alert("Hello, world!"); // 弹窗显示
console.log("Hello, world!"); // 在控制台(console)里显示,需要先开启开发工具控制台

3. 修改WinServer.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024
#define BASE_PATH "D:\\" // 基础文件路径

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
char response_body[BUFFER_SIZE];
FILE* file;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
// 构建文件路径
char file_path[BUFFER_SIZE];
snprintf(file_path, sizeof(file_path), "%s%s", BASE_PATH, path + 1); // 路径前加上基础路径,去掉前面的'/'

// 打开文件并读取内容
file = fopen(file_path, "r");
if (file) {
// 读取文件内容
size_t bytes_read = fread(response_body, sizeof(char), sizeof(response_body) - 1, file);
response_body[bytes_read] = '\0'; // 确保字符串结束
fclose(file);

// 确定 Content-Type
const char* content_type;
if (strstr(path, ".html")) {
content_type = "text/html";
}
else if (strstr(path, ".css")) {
content_type = "text/css";
}
else if (strstr(path, ".js")) { // 添加对JavaScript文件的支持
content_type = "application/javascript";
}
else {
content_type = "application/octet-stream"; // 默认类型
}

// 发送响应头
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %lu\r\n"
"Connection: close\r\n\r\n";
char header[BUFFER_SIZE];
sprintf(header, response_header, content_type, bytes_read);
send(client_socket, header, strlen(header), 0);
send(client_socket, response_body, bytes_read, 0);
}
else {
// 文件未找到
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
}

// 关闭客户端套接字
closesocket(client_socket);
}

int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

4. 运行结果

  1. 运行WinServer.exe

  2. 浏览器中访问http://127.0.0.1:8080/First/First.html

  3. 运行成功

6.设置utf8编码,并让客户端能去除html标签只显示文本内容

WinClient.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define SERVER_IP "127.0.0.1" // 服务器IP地址
#define PORT 8080
#define BUFFER_SIZE 4096

void set_console_utf8() {
// 设置控制台为UTF-8编码
SetConsoleOutputCP(CP_UTF8);
}

void print_html_text(const char* response) {
const char* pos = response;
int in_tag = 0; // 标记是否在标签内

while (*pos) {
if (*pos == '<') {
in_tag = 1; // 进入标签
}
else if (*pos == '>') {
in_tag = 0; // 退出标签
}
else if (!in_tag) {
// 如果不在标签内,打印字符
putchar(*pos);
}
pos++;
}
}

void send_request(const char* path) {
WSADATA wsaData;
SOCKET sock;
struct sockaddr_in server;
char request[BUFFER_SIZE];
char response[BUFFER_SIZE];
int bytes_received;
int header_end = 0; // 标记HTTP头部结束的位置

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return;
}

// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(SERVER_IP);
server.sin_port = htons(PORT);

// 连接到服务器
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Connect failed. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return;
}

// 构建HTTP GET请求
sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", path, SERVER_IP);

// 发送请求
send(sock, request, strlen(request), 0);

// 接收响应
while ((bytes_received = recv(sock, response, sizeof(response) - 1, 0)) > 0) {
response[bytes_received] = '\0'; // 添加字符串结束符

// 查找HTTP头部结束的位置
if (!header_end) {
char* header_end_pos = strstr(response, "\r\n\r\n");
if (header_end_pos) {
header_end = 1; // 找到头部结束
*header_end_pos = '\0'; // 将头部结束符替换为字符串结束符
printf("HTTP Response Headers:\n%s\n", response); // 打印HTTP头部
print_html_text(header_end_pos + 4); // 打印HTML文本内容
}
else {
printf("%s", response); // 打印接收到的内容
}
}
else {
// 头部已经结束,直接打印HTML文本内容
print_html_text(response);
}
}

// 关闭套接字
closesocket(sock);
WSACleanup();
}

int main() {
char path[256];

// 设置控制台为UTF-8编码
set_console_utf8();

// 输入请求路径
printf("Enter the path to request (e.g., /index.html): ");
scanf("%s", path);

// 发送请求
send_request(path);

return 0;
}

WinServer.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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define PORT 8080
#define BUFFER_SIZE 1024
#define BASE_PATH "D:\\" // 基础文件路径

void handle_request(SOCKET client_socket) {
char buffer[BUFFER_SIZE];
int bytes_received = recv(client_socket, buffer, sizeof(buffer) - 1, 0);
if (bytes_received > 0) {
buffer[bytes_received] = '\0'; // 添加字符串结束符
printf("Received request:\n%s\n", buffer);

// 解析请求行
char method[16], path[256], version[16];
sscanf(buffer, "%s %s %s", method, path, version);

// 响应内容
const char* response_header;
char response_body[BUFFER_SIZE];
FILE* file;

// 根据请求路径返回不同的响应
if (strcmp(method, "GET") == 0) {
// 构建文件路径
char file_path[BUFFER_SIZE];
snprintf(file_path, sizeof(file_path), "%s%s", BASE_PATH, path + 1); // 路径前加上基础路径,去掉前面的'/'

// 打开文件并读取内容
file = fopen(file_path, "rb"); // 以二进制模式打开文件
if (file) {
// 读取文件内容
size_t bytes_read = fread(response_body, sizeof(char), sizeof(response_body) - 1, file);
response_body[bytes_read] = '\0'; // 确保字符串结束
fclose(file);

// 确定 Content-Type
const char* content_type;
if (strstr(path, ".html")) {
content_type = "text/html; charset=utf-8"; // 添加字符集
}
else if (strstr(path, ".css")) {
content_type = "text/css; charset=utf-8"; // 添加字符集
}
else if (strstr(path, ".js")) {
content_type = "application/javascript; charset=utf-8"; // 添加字符集
}
else {
content_type = "application/octet-stream"; // 默认类型
}

// 发送响应头
response_header = "HTTP/1.1 200 OK\r\n"
"Content-Type: %s\r\n"
"Content-Length: %lu\r\n"
"Connection: close\r\n\r\n";
char header[BUFFER_SIZE];
sprintf(header, response_header, content_type, bytes_read);
send(client_socket, header, strlen(header), 0);
send(client_socket, response_body, bytes_read, 0);
}
else {
// 文件未找到
response_header = "HTTP/1.1 404 Not Found\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"Connection: close\r\n\r\n";
const char* error_body = "<html><body><h1>404 Not Found</h1></body></html>";
send(client_socket, response_header, strlen(response_header), 0);
send(client_socket, error_body, strlen(error_body), 0);
}
}
}

// 关闭客户端套接字
closesocket(client_socket);
}


int main() {
WSADATA wsaData;
SOCKET server_socket, client_socket;
struct sockaddr_in server, client;
int client_len = sizeof(client);

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY; // 监听所有IP
server.sin_port = htons(PORT);

// 绑定套接字
if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed. Error Code: %d\n", WSAGetLastError());
closesocket(server_socket);
WSACleanup();
return 1;
}

// 开始监听
listen(server_socket, SOMAXCONN);
printf("Server listening on port %d...\n", PORT);

// 主循环,接受客户端连接
while (1) {
client_socket = accept(server_socket, (struct sockaddr*)&client, &client_len);
if (client_socket == INVALID_SOCKET) {
printf("Accept failed. Error Code: %d\n", WSAGetLastError());
continue;
}

// 处理请求
handle_request(client_socket);
}

// 关闭服务器套接字
closesocket(server_socket);
WSACleanup();
return 0;
}

运行结果

  1. 运行WinServer.exe

  2. 运行WinClient.exe后输入html文件路径/First/First.html

  3. 运行成功

7. 用C语言在windows中使用http协议浏览网页http://info.cern.ch/

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
// WinClient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h> // 包含 inet_pton 的定义
#include <conio.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define SERVER "info.cern.ch" // 服务器地址
#define PORT 80 // HTTP端口
#define BUFFER_SIZE 4096

int main() {
WSADATA wsaData;
SOCKET sock;
struct sockaddr_in server;
char request[BUFFER_SIZE], response[BUFFER_SIZE];
int bytes_received;

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_port = htons(PORT);

// 将主机名转换为IP地址
struct hostent* host = gethostbyname(SERVER);
if (host == NULL) {
printf("Could not resolve hostname. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
memcpy(&server.sin_addr, host->h_addr, host->h_length);

struct in_addr addr;
// 获取第一个 IP 地址
addr = *(struct in_addr*)host->h_addr_list[0];
// 打印 IP 地址
printf("IP Address: %s\n", inet_ntoa(addr)); // inet_ntoa 将 in_addr 转换为字符串形式


// 连接到服务器
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Connect failed. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}

// 构建HTTP GET请求
sprintf(request, "GET / HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n\r\n", SERVER);

// 发送请求
send(sock, request, strlen(request), 0);

// 接收响应
while ((bytes_received = recv(sock, response, sizeof(response) - 1, 0)) > 0) {
response[bytes_received] = '\0'; // 添加字符串结束符
printf("%s", response); // 打印响应
}

// 关闭套接字
closesocket(sock);
WSACleanup();
int i = _getche();
return 0;
}

8.用C语言在windows中使用http协议浏览网页http://www.auiou.com/relevant/00000909.jsp,并设置控制台utf8编码

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
// WinClient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h> // 包含 inet_pton 的定义
#include <conio.h>

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996)

#define SERVER "www.auiou.com" // 服务器地址
#define PATH "/relevant/00000909.jsp" // 服务器路径
#define PORT 80 // HTTP端口
#define BUFFER_SIZE 4096

int main() {
SetConsoleOutputCP(CP_UTF8);
WSADATA wsaData;
SOCKET sock;
struct sockaddr_in server;
char request[BUFFER_SIZE], response[BUFFER_SIZE];
int bytes_received;

// 初始化WinSock
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("Failed to initialize WinSock. Error Code: %d\n", WSAGetLastError());
return 1;
}

// 创建套接字
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket. Error Code: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}

// 设置服务器信息
server.sin_family = AF_INET;
server.sin_port = htons(PORT);

// 将主机名转换为IP地址
struct hostent* host = gethostbyname(SERVER);
if (host == NULL) {
printf("Could not resolve hostname. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}
memcpy(&server.sin_addr, host->h_addr, host->h_length);

struct in_addr addr;
// 获取第一个 IP 地址
addr = *(struct in_addr*)host->h_addr_list[0];
// 打印 IP 地址
printf("IP Address: %s\n", inet_ntoa(addr)); // inet_ntoa 将 in_addr 转换为字符串形式


// 连接到服务器
if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
printf("Connect failed. Error Code: %d\n", WSAGetLastError());
closesocket(sock);
WSACleanup();
return 1;
}

// 构建HTTP GET请求
// 发送请求
snprintf(request, sizeof(request),
"GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
"Connection: close\r\n"
"\r\n", PATH, SERVER);

// 发送请求
send(sock, request, strlen(request), 0);

// 接收响应
while ((bytes_received = recv(sock, response, sizeof(response) - 1, 0)) > 0) {
response[bytes_received] = '\0'; // 添加字符串结束符
printf("%s", response); // 打印响应
}

// 关闭套接字
closesocket(sock);
WSACleanup();
int i = _getche();
return 0;
}