实战案例3:C语言实现的HTTP服务器

简介: 实战案例3:C语言实现的HTTP服务器

实战案例3:C语言实现的HTTP服务器

详细解析如何用C语言实现一个基本的HTTP服务器,处理GET和POST请求。

 

 

创建一个简单的HTTP服务器以处理GET和POST请求在C语言中是一个很好的学习项目,因为它涉及到了网络编程、字符串处理以及HTTP协议的基础知识。下面,我将逐步介绍如何使用C语言和socket编程来实现这样的服务器。

1. 准备工作

首先,确保你的系统上安装了C编译器,如GCC。此外,你需要了解socket编程的基本概念,包括TCP/IP协议栈、套接字(sockets)等。

2. 编写HTTP服务器的基本框架

2.1 包含必要的头文件

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <netinet/in.h>

#include <sys/socket.h>

2.2 初始化socket

int create_socket(int port) {

int server_fd, yes = 1;

struct sockaddr_in address;

int opt = 1;

 

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

perror("socket failed");

exit(EXIT_FAILURE);

}

 

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {

perror("setsockopt");

exit(EXIT_FAILURE);

}

 

address.sin_family = AF_INET;

address.sin_addr.s_addr = INADDR_ANY;

address.sin_port = htons(port);

 

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {

perror("bind failed");

exit(EXIT_FAILURE);

}

 

if (listen(server_fd, 3) < 0) {

perror("listen");

exit(EXIT_FAILURE);

}

 

return server_fd;

}

2.3 处理HTTP请求

你需要解析传入的HTTP请求,并根据请求类型(GET或POST)来响应。这里为了简化,我们仅处理GET请求,并发送一个简单的HTML页面作为响应。

void handle_request(int sock) {

char buffer[1024] = {0};

read(sock, buffer, 1024);

 

printf("HTTP request:\n%s\n", buffer);

 

// 这里假设只处理GET请求

if (strstr(buffer, "GET / ") != NULL) {

const char *http_response = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<html><body><h1>Hello, World!</h1></body></html>";

write(sock, http_response, strlen(http_response));

}

 

close(sock);

}

2.4 主函数

int main(int argc, char *argv[]) {

int server_fd, new_socket;

struct sockaddr_in address;

int opt = sizeof(address);

 

if (argc != 2) {

fprintf(stderr, "Usage: %s <port>\n", argv[0]);

exit(EXIT_FAILURE);

}

 

server_fd = create_socket(atoi(argv[1]));

 

while (1) {

if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&opt)) < 0) {

perror("accept");

exit(EXIT_FAILURE);

}

 

// 创建子进程处理请求

pid_t pid = fork();

 

if (pid == 0) {

// 子进程

close(server_fd);

handle_request(new_socket);

exit(0);

} else {

// 父进程

close(new_socket);

}

}

 

return 0;

}

3. 编译和运行

将上述代码保存为http_server.c,并使用GCC编译:

gcc http_server.c -o http_server

然后,运行服务器:

./http_server 8080

在浏览器中访问http://localhost:8080/,你应该能看到“Hello, World!”的页面。

 

 

实战案例3:C语言实现的HTTP服务器(扩展)

在构建一个简单的HTTP服务器时,我们需要处理网络通信、请求解析以及响应生成等多个技术环节。以下是一个详细的步骤和代码示例,用于创建一个能够处理GET请求的HTTP服务器,并返回“Hello, World!”的HTML页面。此代码将基于C语言,使用标准的socket编程技术。

1. 包含必要的头文件

首先,我们需要包含处理网络通信和字符串操作所需的头文件。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

2. 定义常量和全局变量

为了方便管理,我们定义一些常量来表示网络地址族、套接字类型以及HTTP响应等。

#define PORT 8080

#define BUFFER_SIZE 1024

 

const char* http_response =

"HTTP/1.1 200 OK\r\n"

"Content-Type: text/html\r\n"

"\r\n"

"<html><body><h1>Hello, World!</h1></body></html>";

3. 创建套接字函数

接下来,我们编写一个函数来创建并配置套接字。

int create_socket(int port) {

int server_fd, yes = 1;

struct sockaddr_in address;

int opt = 1;

 

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {

perror("socket failed");

exit(EXIT_FAILURE);

}

 

if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) < 0) {

perror("setsockopt");

close(server_fd);

exit(EXIT_FAILURE);

}

 

address.sin_family = AF_INET;

address.sin_addr.s_addr = INADDR_ANY;

address.sin_port = htons(port);

 

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {

perror("bind failed");

close(server_fd);

exit(EXIT_FAILURE);

}

 

if (listen(server_fd, 3) < 0) {

perror("listen");

close(server_fd);

exit(EXIT_FAILURE);

}

 

return server_fd;

}

4. 处理HTTP请求的函数

然后,我们定义一个函数来接收HTTP请求,并发送响应。

void handle_request(int sock) {

char buffer[BUFFER_SIZE] = {0};

int valread = read(sock, buffer, BUFFER_SIZE);

printf("HTTP request:\n%s\n", buffer);

 

if (strstr(buffer, "GET / ") != NULL) {

write(sock, http_response, strlen(http_response));

} else {

// 可以处理其他类型的HTTP请求或发送错误响应

const char* error_response =

"HTTP/1.1 404 Not Found\r\n"

"Content-Type: text/plain\r\n"

"\r\n"

"404 Not Found";

write(sock, error_response, strlen(error_response));

}

 

close(sock);

}

5. 主函数

最后,我们在主函数中启动服务器,并等待连接。

int main(int argc, char *argv[]) {

int server_fd = create_socket(PORT);

struct sockaddr_in client_addr;

socklen_t len = sizeof(client_addr);

 

printf("Server is listening on port %d...\n", PORT);

 

while (1) {

int sock = accept(server_fd, (struct sockaddr *)&client_addr, &len);

if (sock < 0) {

perror("accept failed");

continue;

}

 

printf("Accepted new connection from %s:%d\n",

inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

 

// 处理

 

相关文章
|
4月前
|
人工智能 JavaScript API
零基础构建MCP服务器:TypeScript/Python双语言实战指南
作为一名深耕技术领域多年的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP作为Anthropic推出的开放标准,正在重新定义AI应用与外部系统的交互方式,它不仅解决了传统API集成的复杂性问题,更为开发者提供了一个统一、安全、高效的连接框架。在过去几个月的实践中,我发现许多开发者对MCP的概念理解透彻,但在实际动手构建MCP服务器时却遇到了各种技术壁垒。从环境配置的细节问题到SDK API的深度理解,从第一个Hello World程序的调试到生产环境的部署优化,每一个环节都可能成为初学者的绊脚石。因此,我决定撰写这篇全面的实
829 67
零基础构建MCP服务器:TypeScript/Python双语言实战指南
|
28天前
|
存储 运维 数据挖掘
服务器数据恢复—EqualLogic存储硬盘出现坏道的数据恢复案例
某品牌EqualLogic PS6100存储阵列上有一组由16块硬盘组建的raid5磁盘阵列。磁盘阵列上层划分多个大小不同的卷,存放虚拟机文件。 硬盘出现故障导致存储阵列不可用,需要恢复存储阵列中的数据。
|
1月前
|
存储 运维 Oracle
服务器数据恢复—存储硬盘指示灯亮黄灯,RAID5阵列崩溃的数据恢复案例
服务器存储数据恢复环境: 某单位一台某品牌DS5300存储,1个机头+4个扩展柜,50块的硬盘组建了两组RAID5阵列。一组raid5阵列有27块硬盘,存放Oracle数据库文件。存储系统上层一共划分了11个卷。 服务器存储故障: 存储设备上两个硬盘指示灯亮黄色。其中一组RAID5阵列崩溃,存储不可用,设备已经过保。
|
29天前
|
弹性计算 人工智能 前端开发
在阿里云ECS上部署n8n自动化工作流:U2实例实战
本文介绍如何在阿里云ECS的u2i/u2a实例上部署开源工作流自动化平台n8n,利用Docker快速搭建并配置定时任务,实现如每日抓取MuleRun新AI Agent并推送通知等自动化流程。内容涵盖环境准备、安全组设置、实战案例与优化建议,助力高效构建低维护成本的自动化系统。
331 5
|
2月前
|
Unix 应用服务中间件 索引
服务器数据恢复—LUN映射出错导致文件系统共享冲突的数据恢复案例
SUN光纤存储系统中有一组由6个硬盘组建的RAID6,划分为若干LUN,MAP到跑不同业务的服务器上,这些服务器上运行的是SOLARIS操作系统。 服务器不存在物理故障。由于公司业务变化,需要增加一台服务器跑新的应用。服务器管理员在原服务器在线的状态下,将其中一个lun映射到一台新服务器上。实际上,这个刚映射过去的卷已经map到了solaris生产系统上的某个lun上了。映射到新服务器后,服务器对这个卷进行初始化的操作,原solaris系统上的磁盘报错,重启服务器后这个卷已经无法挂载。 服务器管理员寻求sun原厂工程师的帮助。sun工程师检测后执行了fsck操作。执行完成后文件系统挂载成功。查
|
2月前
|
存储 数据挖掘 Linux
服务器数据恢复—重装系统导致OceanStor存储上的分区无法访问的数据恢复案例
服务器存储数据恢复环境: 华为OceanStor某型号存储+扩展盘柜,存储中的硬盘组建了raid5磁盘阵列,上层分配了1个lun。 linux操作系统,划分了两个分区,分区一通过lvm扩容,分区二为xfs文件系统。 服务器存储故障: 工作人员重装系统操作失误导致磁盘分区变化,分区二无法访问,数据丢失。
|
2月前
|
存储 数据挖掘 Windows
服务器数据恢复—RAIDZ上层ZFS文件系统数据恢复案例
一台服务器有32块硬盘,采用Windows操作系统。 服务器在正常运行的时候突然变得不可用。没有异常断电、进水、异常操作、机房不稳定等外部因素。服务器管理员重启服务器,但是服务器无法进入系统。管理员联系北亚企安数据恢复工程师要求恢复服务器数据。
|
3月前
|
存储 算法 数据挖掘
服务器数据恢复—昆腾存储StorNext文件系统数据恢复案例
一台昆腾存储设备中有一组raid5磁盘阵列。阵列上有两块硬盘先后离线,raid5磁盘阵列不可用。
|
2月前
|
存储
服务器数据恢复—服务器断电导致数据丢失的数据恢复案例
某品牌服务器中有12块硬盘,组建了一组raid5磁盘阵列,服务器内存储的是普通文件。 机房供电不稳定导致服务器断电,管理员重启服务器后发现服务器无法正常工作。 根据描述的故障发生过程,北亚企安数据恢复工程师推断故障是意外断电导致raid模块损坏。
|
3月前
|
小程序 数据挖掘
服务器数据恢复—服务器上的卷被误删除的数据恢复案例
工作人员不慎将一台服务器上的卷误删除,服务器上有一组raid5阵列。需要恢复误删除的数据。