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

 

// 处理

 

目录
相关文章
|
19天前
|
运维 数据挖掘 开发工具
服务器数据恢复—硬盘离线导致raid5阵列热备盘上线失败的数据恢复案例
服务器磁盘阵列数据恢复环境: 服务器中有两组分别由4块SAS硬盘组建的raid5磁盘阵列,两组raid5阵列划分LUN,组成LVM结构,格式化为EXT3文件系统。 服务器磁盘阵列故障: 服务器中一组raid5阵列中有一块硬盘离线,热备盘自动上线替换离线硬盘。热备盘上线同步数据过程中又有一块硬盘离线,热备盘同步失败,该组raid5阵列崩溃,LVM结构变得不完整,文件系统无法使用。 硬件工程师对两块离线硬盘进行硬件故障检测,发现先离线硬盘无法识别,初步判断该硬盘存在硬件故障,需要进行开盘修复。后离线硬盘可以正常识别。
服务器数据恢复—硬盘离线导致raid5阵列热备盘上线失败的数据恢复案例
|
28天前
|
SQL 数据挖掘 数据库
服务器数据恢复—意外断电导致XenServer虚拟机不可用的数据恢复案例
服务器数据恢复环境: 一台服务器中有一组由4块STAT硬盘通过RAID卡组建的RAID10阵列,上层是XenServer虚拟化平台,虚拟机安装Windows Server操作系统,作为Web服务器使用。 服务器故障: 因机房异常断电导致服务器中一台VPS(Xen Server虚拟机)不可用,虚拟磁盘文件丢失。
服务器数据恢复—意外断电导致XenServer虚拟机不可用的数据恢复案例
|
9天前
|
存储 数据挖掘 数据库
服务器数据恢复—raid磁盘故障导致数据库数据损坏的数据恢复案例
存储中有一组由3块SAS硬盘组建的raid。上层win server操作系统层面划分了3个分区,数据库存放在D分区,备份存放在E分区。 RAID中一块硬盘的指示灯亮红色,D分区无法识别;E分区可识别,但是拷贝文件报错。管理员重启服务器,导致离线的硬盘上线开始同步数据,同步还没有完成就直接强制关机了,之后就没有动过服务器。
|
14天前
|
JavaScript 前端开发
vue配合axios连接express搭建的node服务器接口_简单案例
文章介绍了如何使用Express框架搭建一个简单的Node服务器,并使用Vue结合Axios进行前端开发和接口调用,同时讨论了开发过程中遇到的跨域问题及其解决方案。
13 0
vue配合axios连接express搭建的node服务器接口_简单案例
|
18天前
|
机器学习/深度学习 JSON API
HTTP协议实战演练场:Python requests库助你成为网络数据抓取大师
在数据驱动的时代,网络数据抓取对于数据分析、机器学习等至关重要。HTTP协议作为互联网通信的基石,其重要性不言而喻。Python的`requests`库凭借简洁的API和强大的功能,成为网络数据抓取的利器。本文将通过实战演练展示如何使用`requests`库进行数据抓取,包括发送GET/POST请求、处理JSON响应及添加自定义请求头等。首先,请确保已安装`requests`库,可通过`pip install requests`进行安装。接下来,我们将逐一介绍如何利用`requests`库探索网络世界,助你成为数据抓取大师。在实践过程中,务必遵守相关法律法规和网站使用条款,做到技术与道德并重。
30 2
|
25天前
|
数据采集 网络协议 API
HTTP协议大揭秘!Python requests库实战,让网络请求变得简单高效
【9月更文挑战第13天】在数字化时代,互联网成为信息传输的核心平台,HTTP协议作为基石,定义了客户端与服务器间的数据传输规则。直接处理HTTP请求复杂繁琐,但Python的`requests`库提供了一个简洁强大的接口,简化了这一过程。HTTP协议采用请求与响应模式,无状态且结构化设计,使其能灵活处理各种数据交换。
48 8
|
27天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
26天前
|
存储 数据挖掘 Linux
服务器数据恢复—Linux操作系统网站服务器数据恢复案例
服务器数据恢复环境: 一台linux操作系统服务器上跑了几十个网站,服务器上只有一块SATA硬盘。 服务器故障: 服务器突然宕机,尝试再次启动失败。将硬盘拆下检测,发现存在坏扇区
|
27天前
|
开发者
HTTP状态码是由网页服务器返回的三位数字响应代码,用于表示请求的处理结果和状态
HTTP状态码是由网页服务器返回的三位数字响应代码,用于表示请求的处理结果和状态
24 1
|
29天前
|
存储 算法 C语言
C语言手撕实战代码_二叉排序树(二叉搜索树)_构建_删除_插入操作详解
这份二叉排序树习题集涵盖了二叉搜索树(BST)的基本操作,包括构建、查找、删除等核心功能。通过多个具体示例,如构建BST、查找节点所在层数、删除特定节点及查找小于某个关键字的所有节点等,帮助读者深入理解二叉排序树的工作原理与应用技巧。此外,还介绍了如何将一棵二叉树分解为两棵满足特定条件的BST,以及删除所有关键字小于指定值的节点等高级操作。每个题目均配有详细解释与代码实现,便于学习与实践。

热门文章

最新文章