题目4:标准C语言实现简单Web服务器 设计目标: 完成基础的tcp连接,支持基础的client与其连接使用fork()来支持并发访问服务器简单的http访问,支持静态页面访问 支持静态页面访问,需要一定的报错机制,如404页面的建立。 1. socket实现简单Http服务器,完成html的解析; 2. 运行该服务器可以通过浏览器访问服务器目录下的 Html文件、jpg图片、css文件的载入。 完成初步的Http服务器功能。
时间: 2024-02-20 16:00:31 浏览: 78
c语言多进程tcp服务器示例
下面是一个基于标准C语言实现的简单Web服务器,支持静态页面访问和404页面的建立。该服务器使用了Socket编程和fork()来支持并发访问。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define PORT 8888
#define MAXLINE 1024
#define ROOT "/path/to/root"
void handle_request(int sockfd);
void send_file(int sockfd, const char *path);
void send_not_found(int sockfd);
int main()
{
int serv_sock, clnt_sock;
struct sockaddr_in serv_addr, clnt_addr;
socklen_t clnt_addr_len;
pid_t pid;
serv_sock = socket(AF_INET, SOCK_STREAM, 0);
if (serv_sock < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);
if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(serv_sock, 5) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);
while (1) {
clnt_addr_len = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
if (clnt_sock < 0) {
perror("accept");
continue;
}
pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) {
close(serv_sock);
handle_request(clnt_sock);
exit(EXIT_SUCCESS);
} else {
close(clnt_sock);
}
}
close(serv_sock);
return 0;
}
void handle_request(int sockfd)
{
char buf[MAXLINE];
int n;
memset(buf, 0, MAXLINE);
n = recv(sockfd, buf, MAXLINE, 0);
if (n < 0) {
perror("recv");
exit(EXIT_FAILURE);
}
char *method = strtok(buf, " ");
char *path = strtok(NULL, " ");
char *http_version = strtok(NULL, "\r\n");
if (strcmp(method, "GET") != 0) {
printf("Unsupported method: %s\n", method);
exit(EXIT_FAILURE);
}
if (strcmp(http_version, "HTTP/1.0") != 0 && strcmp(http_version, "HTTP/1.1") != 0) {
printf("Unsupported HTTP version: %s\n", http_version);
exit(EXIT_FAILURE);
}
if (strncmp(path, "/", 1) == 0) {
path = "/index.html";
}
char file_path[MAXLINE];
snprintf(file_path, MAXLINE, "%s%s", ROOT, path);
if (access(file_path, F_OK) == -1) {
send_not_found(sockfd);
} else {
send_file(sockfd, file_path);
}
close(sockfd);
}
void send_file(int sockfd, const char *path)
{
struct stat st;
int file_fd, file_size, n;
char buf[MAXLINE];
file_fd = open(path, O_RDONLY);
if (file_fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
fstat(file_fd, &st);
file_size = st.st_size;
snprintf(buf, MAXLINE, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", file_size);
send(sockfd, buf, strlen(buf), 0);
while ((n = read(file_fd, buf, MAXLINE)) > 0) {
send(sockfd, buf, n, 0);
}
close(file_fd);
}
void send_not_found(int sockfd)
{
char buf[MAXLINE];
int n;
snprintf(buf, MAXLINE, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1><p>The requested URL was not found on this server.</p></body></html>");
send(sockfd, buf, strlen(buf), 0);
}
```
该服务器使用了ROOT常量来指定静态页面的根目录,可以根据实际情况进行修改。在handle_request()函数中,首先解析HTTP请求,然后根据请求的路径来打开对应的文件。如果文件不存在,则发送404 Not Found响应,否则发送文件内容作为响应。send_not_found()函数用于发送404 Not Found响应。
阅读全文