实战案例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));

 

// 处理

 

目录
相关文章
|
24天前
|
存储 数据挖掘 Windows
服务器数据恢复—V7000存储raid5故障导致LUN无法访问的数据恢复案例
服务器数据恢复环境: 三台V7000存储,共有64块SAS硬盘(其中有三块热备盘,其中一块已启用)组建了数组raid5阵列。分配若干LUN,上层安装Windows server操作系统,数据分区格式化为NTFS文件系统。 服务器故障: V7000存储中有多块硬盘出现故障离线,阵列失效,LUN无法访问。需要恢复卷中所有数据(主要为dcm文件)。
|
25天前
|
Oracle 关系型数据库 数据挖掘
服务器数据恢复—服务器RAID5磁盘阵列数据恢复案例
服务器数据恢复环境: 一台服务器上有一组由5块硬盘(4块数据盘+1块热备盘)组建的raid5阵列。服务器安装Linux Redhat操作系统,运行一套基于oracle数据库的OA系统。 服务器故障: 这组raid5阵列中一块磁盘离线,但是热备盘并没有自动激活rebuild,当另外一块数据盘发生故障离线后,raid崩溃。 用户方要求恢复raid数据,同时要求还原操作系统。经过初步观察,raid中的这些硬盘没有表现出存在明显的物理故障的特征,也没有明显的同步表现,数据恢复的可能性很大。
|
30天前
|
存储 数据挖掘 虚拟化
服务器数据恢复—Raid5阵列两块硬盘硬件故障掉线的数据恢复案例
服务器数据恢复环境: 一台某品牌存储设备上有一组由10块硬盘(9块数据盘+1块热备盘)组建的raid5阵列,上层部署vmware exsi虚拟化平台。 服务器故障: raid5阵列中两块硬盘对应的指示灯亮黄灯掉线。硬盘序列号无法读取,通过SAS扩展卡也无法读取。
|
28天前
|
存储
服务器数据恢复—EMC存储RAID5阵列崩溃的数据恢复案例
服务器数据恢复环境: 一台EMC某型号存储设备,该存储中有一组由12块(包括2块热备盘)STAT硬盘组建的raid5阵列。 服务器故障: 该存储在运行过程中突然崩溃,raid瘫痪。数据恢复工程师到达现场对故障存储设备进行初检,发现raid中有两块硬盘掉线但只有一块热备盘成功激活,所以导致阵列瘫痪,上层lun无法使用。
|
3天前
|
存储 Oracle 关系型数据库
服务器数据恢复—EVA存储硬盘读写性能不稳定掉线的数据恢复案例
服务器存储数据恢复环境: 一台EVA某型号控制器+EVA扩展柜+FC磁盘。 服务器存储故障&检测: 磁盘故障导致该EVA存储中LUN不可用,导致上层应用无法正常使用。
63 47
|
2天前
|
数据挖掘 Linux 数据库
服务器数据恢复—reiserfs文件系统数据恢复案例
服务器数据恢复环境: 一台服务器中有一组由4块SAS硬盘组建的RAID5阵列,上层安装linux操作系统统。分区结构:boot分区+LVM卷+swap分区(按照顺序),LVM卷中划分了一个reiserfs文件系统作为根分区。 服务器故障: 服务器操作系统在运行过程中由于未知原因崩溃,管理员重装操作系统后发现分区结构变为:boot分区+swap分区+LVM卷(按照顺序),LVM卷中文件系统位置有个空的reiserfs超级块。 用户方需要恢复reiserfs文件系统中所有数据,包含数据库、网站程序与网页、OA系统中所有办公文档。
服务器数据恢复—reiserfs文件系统数据恢复案例
|
11天前
|
机器学习/深度学习 弹性计算 运维
云计算系列之阿里云ECS服务器管理实战
本文档介绍了阿里云ECS(Elastic Compute Service)的基本概念、实例管理、磁盘操作、快照与镜像功能及其应用场景,最后通过具体案例解析ECS的实际应用。ECS是阿里云提供的高效、可靠的云计算服务,支持多种业务需求,如Web应用、高并发网站、数据库等,帮助企业快速构建稳定安全的应用,提升运维效率,降低IT成本。文档还详细说明了ECS实例的创建方式、连接方法及日常管理操作,帮助用户更好地利用ECS服务。
44 2
云计算系列之阿里云ECS服务器管理实战
|
5天前
|
存储 数据挖掘
服务器数据恢复—EqualLogic存储raid5阵列多块硬盘掉线的数据恢复案例
服务器存储数据恢复环境: 一台EqualLogic存储中有一组由16块SAS硬盘组建的RAID5阵列。上层划分了4个卷,采用VMFS文件系统,存放虚拟机文件。 服务器存储故障: 存储RAID5阵列中磁盘出现故障,有2块硬盘对应的指示灯亮黄灯,存储不可用,且存储设备已经过保。
|
4天前
|
存储 运维 数据挖掘
服务器数据恢复—EVA存储删除VDISK的数据恢复案例
服务器存储数据恢复环境: 某单位有一台EVA某型号存储主机+2个扩展柜,共12个FATA磁盘+10个FC磁盘,LUN数量不确定,操作系统为WINDOWS SERVER。该存储用来存放单位的历史案例审理材料。 服务器存储故障&检测: 该EVA存储出现故障,无法正常使用。而且经过几家数据恢复服务商的操作,具体故障原因已经无法确定。
|
30天前
使用Netty实现文件传输的HTTP服务器和客户端
本文通过详细的代码示例,展示了如何使用Netty框架实现一个文件传输的HTTP服务器和客户端,包括服务端的文件处理和客户端的文件请求与接收。
32 1
使用Netty实现文件传输的HTTP服务器和客户端