1、发送HTTP响应的函数
用于发送HTTP响应的函数。它向客户端发送一个包含状态行、响应头和HTML内容的HTTP响应。
HTTP/1.1 200 OK
:表示服务器处理请求成功,返回状态码 200。
Content-Type: text/html
:表示返回的数据类型是HTML格式。
Content-Length: 51
:表示HTML内容的长度为 51 字节。
<html>...</html>
:HTML内容,表示服务器返回的页面内容是一个简单的HTML页面。
write()
向客户端发送数据。client_socket 是与客户端通信的套接字。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 // 服务器监听的端口号 #define BUFFER_SIZE 1024 // 发送HTTP响应 void send_http_response(int client_socket) { char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Content-Length: 51\r\n" "\r\n" "<html><body><h1>Hello, C HTTP Server!</h1></body></html>"; write(client_socket, response, sizeof(response) - 1); }
2、创建绑定服务器套接字
socket()
创建一个套接字。AF_INET
是指定使用IPv4地址。SOCK_STREAM
是指定使用TCP连接。0
是协议自动选择为TCP。如果 socket()
返回 -1
,表示创建失败,此时程序调用 perror()
输出错误信息并退出。bind()
将套接字与服务器的IP地址和端口号绑定。如果绑定失败,程序输出错误信息并退出。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 // 服务器监听的端口号 #define BUFFER_SIZE 1024 int main() { int server_socket, client_socket; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len = sizeof(client_addr); char buffer[BUFFER_SIZE]; // 创建服务器套接字 server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket == -1) { perror("无法创建套接字"); exit(EXIT_FAILURE); } // 设置服务器地址 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口 server_addr.sin_port = htons(PORT); // 端口号 // 绑定套接字到指定的端口 if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("绑定失败"); close(server_socket); exit(EXIT_FAILURE); } // 监听客户端连接请求 if (listen(server_socket, 10) == -1) { perror("监听失败"); close(server_socket); exit(EXIT_FAILURE); } printf("服务器启动,正在监听端口 %d...\n", PORT); }
3、接受读取客户端请并响应
accept()
接受客户端连接,并为该连接创建一个新的套接字 client_socket
。如果接收失败,程序输出错误信息并继续等待下一个连接。调用之前定义的send_http_response()
函数,向客户端发送HTTP响应。
while (1) { // 接受客户端连接 client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len); if (client_socket == -1) { perror("接受客户端连接失败"); continue; } // 清空缓冲区,接收客户端发送的数据 memset(buffer, 0, BUFFER_SIZE); read(client_socket, buffer, BUFFER_SIZE - 1); printf("接收到的请求:\n%s\n", buffer); // 发送HTTP响应 send_http_response(client_socket); // 关闭客户端连接 close(client_socket); } // 关闭服务器套接字 close(server_socket);
4、完整代码
一个简易的HTTP服务器,可以根据自己的需求进行扩展和完善。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8080 // 服务器监听的端口号 #define BUFFER_SIZE 1024 // 发送HTTP响应 void send_http_response(int client_socket) { char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Content-Length: 51\r\n" "\r\n" "<html><body><h1>Hello, C HTTP Server!</h1></body></html>"; write(client_socket, response, sizeof(response) - 1); } int main() { int server_socket, client_socket; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len = sizeof(client_addr); char buffer[BUFFER_SIZE]; // 创建服务器套接字 server_socket = socket(AF_INET, SOCK_STREAM, 0); if (server_socket == -1) { perror("无法创建套接字"); exit(EXIT_FAILURE); } // 设置服务器地址 server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网络接口 server_addr.sin_port = htons(PORT); // 端口号 // 绑定套接字到指定的端口 if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("绑定失败"); close(server_socket); exit(EXIT_FAILURE); } // 监听客户端连接请求 if (listen(server_socket, 10) == -1) { perror("监听失败"); close(server_socket); exit(EXIT_FAILURE); } printf("服务器启动,正在监听端口 %d...\n", PORT); // 主循环,处理客户端连接 while (1) { // 接受客户端连接 client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len); if (client_socket == -1) { perror("接受客户端连接失败"); continue; } // 清空缓冲区,接收客户端发送的数据 memset(buffer, 0, BUFFER_SIZE); read(client_socket, buffer, BUFFER_SIZE - 1); printf("接收到的请求:\n%s\n", buffer); // 发送HTTP响应 send_http_response(client_socket); // 关闭客户端连接 close(client_socket); } // 关闭服务器套接字 close(server_socket); return 0; }