iis服务器助手广告广告
返回顶部
首页 > 资讯 > 服务器 >如何用C写一个web服务器之基础功能
  • 789
分享到

如何用C写一个web服务器之基础功能

2024-04-02 19:04:59 789人浏览 安东尼
摘要

目录服务器架构目标架构当前状态功能实现Socket系列方法服务器与 PHP cli 交互报文数据处理服务器架构 目标架构 以 Nginx 的思想来考虑本服务器架构,初步考虑如下图:

服务器架构

目标架构

Nginx 的思想来考虑本服务器架构,初步考虑如下图:

当然 php 进程也可以替换为其他的脚本语言,可以更改源码中的 command 变量实现。

服务器有一个 master 进程,其有多个子进程为 worker 进程,master 进程受理客户端的请求,然后分发给 worker 进程,worker 进程处理 Http 头信息后将参数传递给 php 进程处理后,将结果返回到上层,再响应给客户端。

也考虑过使用 php-fpm 的 worker 进程池方式,那样的话 php-fpm 进程也要仿写了,目前还不熟悉其内部构造,如果可以简单化,自然向其靠拢。目前对 PHP 的 Sapi 接口不熟,了解一下再考虑。

当前状态

当前状态的服务器还极其简单,总结下来有以下地方待优化

  • 当前还是单进程,需要改成多进程,最终为 worker 进程池方式;
  • 优化 socket io 模型,考虑 epoll、事件驱动方式;
  • 只支持 HTTP GET 请求方法,未进行太多的异常处理来定义 http 状态码;
  • 与 php 进程的交互方式,考虑如 nginx 使用 unix domain socket 方式。
  • 协议目前只考虑了 http,后续会考虑一些基于 tcp 的协议;

虽然简单,但服务器已经有基本的功能了:

它监听本地地址的 8080 端口,将接收到的 http 头中的 path 信息提出出来交给 php 进程,php 进程将参数信息处理后返回给服务器,服务器拼装 http 响应信息再将结果返回给客户端。

下面介绍各个功能的实现:

功能实现

socket系列方法

在介绍函数之间先用一张图来介绍一次 http 请求中客户端与服务器之间的交互:

如图:服务器创建要进行:

1.调用 socket() 创建一个连接;int socket(int domain, int type, int protocol);

2.调用 bind() 给套接字命名,绑定端口;int bind( int socket, const struct sockaddr *address, size_t address_len);

3.调用 listen() 监听此套接字;int listen(int socket, int backlog);

4.调用 accept() 接受客户端的连接;int accept(int socket, struct sockaddr *address, size_t *address_len);

5.调用 recv() 接收客户端的信息;int recv(int s, void *buf, int len, unsigned int flags);

6.调用 send() 将响应信息发送给客户端;int send(int s, const void * msg, int len, unsigned int falgs);

socket 间的接收和发送信息在 C 中有几个系列:write() / read() 、send() / recv() 、sendto() / recvfrom()、 sendmsg() / recvmsg(),可以自行选用。

另外函数参数释义和要点,都被我注释在代码中了,感兴趣的可以拉下来看一下,这些在网上也多有介绍,这里不再赘述。

服务器与 PHP cli 交互

然后是 C 进程和 php 进程的交互,考虑到简单易用,目前在 C 进程中直接执行 php 脚本:

一开始使用 system() 函数: int system(const char *command);

system 函数会 fork 一个子进程,在子进程中以 cli 方式执行 php 脚本,并将错误码或返回值返回。由于其结果类型不可控,编译时会报一个 warning。而且它将结果返回给父进程时,还会在标准输出中打印结果,在服务器执行时会抛出异常。

于是找到了另一个方法 popen, FILE * popen(const char * command, const char * type);:

popen 同样会 fork 一个子进程来执行 command ,然后建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。

其 type 参数便是控制连接到子进程的标准输入还是标准输出。我们想要子进程的标准输出,于是传入 type参数为 字符 “r” (read)。同理,如果想写入子进程标准输入的话,可以传值 “w”(write)。

另外在接收缓冲区内容的时候也出现了一点小意外:由于使用的 fgets() 方法会以换行符\n为一段的结尾,在接收 php 进程输出时遇到换行会结束,这里使用了一个中间字符串数组line来接收每一行的信息,将每一行的信息拼装到结果中。

代码如下:


char * execPHP(char *args){
    // 这里不能用变长数组,需要给command留下足够长的空间,以存储args参数,不然拼接参数时会栈溢出
    char command[BUFF_SIZE] = "php /Users/mfhj-dz-001-441/CLionProjects/cproject/tinyServer/index.php ";
    FILE *fp;
    static char buff[BUFF_SIZE]; // 声明静态变量以返回变量指针地址
    char line[BUFF_SIZE];
    strcat(command, args);
    memset(buff, 0, BUFF_SIZE); // 静态变量会一直保留,这里初始化一下
    if((fp = popen(command, "r")) == NULL){
        strcpy(buff, "服务器内部错误");
    }else{
        // fgets会在获取到换行时停止,这里将每一行拼接起来
        while (fgets(line, BUFF_SIZE, fp) != NULL){
        strcat(buff, line);
        };
    }

    return buff;
}

报文数据处理

socket 处于应用层和传输层之间的虚拟层,由于设置服务器 socket 协议类型为 TCP,那么 TCP 的握手挥手、数据读取等步骤对于我们都是透明的。我们拿到的数据即 HTTP 报文,关于 HTTP 报文结构和其字段解释的文章非常多,这里也不再多提。

首先使用 C 的 strtok() 方法,获取到 HTTP 头的第一行,获取到其 http 方法和 path 信息,将这些信息处理后,再使用 sprintf() 方法拼合 HTTP 响应报文,主要替换了 响应内容长度和响应内容。

以上就是如何用C写一个WEB服务器之基础功能的详细内容,更多关于用C写一个web服务器之基础功能的资料请关注编程网其它相关文章!

--结束END--

本文标题: 如何用C写一个web服务器之基础功能

本文链接: https://www.lsjlt.com/news/126921.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何用C写一个web服务器之基础功能
    目录服务器架构目标架构当前状态功能实现socket系列方法服务器与 PHP cli 交互报文数据处理服务器架构 目标架构 以 nginx 的思想来考虑本服务器架构,初步考虑如下图: ...
    99+
    2022-11-12
  • 怎么用C写一个web服务器之基础功能
    这篇文章给大家分享的是有关怎么用C写一个web服务器之基础功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。服务器架构目标架构以 nginx 的思想来考虑本服务器架构,初步考虑如下图:当然 php 进程也可以替换...
    99+
    2023-06-15
  • 如何用C写一个web服务器之CGI协议
    目录前言CGICGI请求CGI响应Nginx和PHP的CGI实现SAPIPHP-FPM纠偏代码实现http_parsercJSON前言 这次更新主要实现一下 CGI 协议。 先放上G...
    99+
    2022-11-12
  • 如何用C写一个web服务器之GCC项目编译
    目录前言编译步骤静态库和动态库静态库动态库CMakeLists前言 本想着接下来大概实现一下 CGI 协议,但是实现过程中被一个问题卡住了: C进程与php进程的交互数据类型问题: ...
    99+
    2022-11-12
  • 如何用C写一个web服务器之I/O多路复用
    目录前言I/O模型select/poll/epollepoll介绍epoll_createepoll_ctlepoll_waitepoll行为代码实现整体处理逻辑设置epoll ET...
    99+
    2022-11-12
  • 怎么用C写一个web服务器之GCC项目编译
    这篇文章给大家分享的是有关怎么用C写一个web服务器之GCC项目编译的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言本想着接下来大概实现一下 CGI 协议,但是实现过程中被一个问题卡住了:C进程与php进程的交...
    99+
    2023-06-15
  • 怎么用C写一个web服务器之I/O多路复用
    小编给大家分享一下怎么用C写一个web服务器之I/O多路复用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前言I/O模型接触过 socket 编程的同学应该都知道...
    99+
    2023-06-15
  • 探索如何用Golang实现一个基础的画布功能
    Golang是一种高效的编程语言,以其简单的语法和良好的性能受到许多程序员的青睐。而画布是一个很常见的需求,尤其是在一些图形处理或游戏开发中。今天,我们来探索如何用Golang实现一个基础的画布。首先,我们需要引入一些Golang的库来实现...
    99+
    2023-05-14
  • 如何用C#编写一个Windows服务程序
    今天小编给大家分享一下如何用C#编写一个Windows服务程序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。添加引用Wind...
    99+
    2023-07-05
  • 如何用Golang搭建一个高性能web服务器
    一个高性能web服务器随着互联网越来越成为人们生活中不可或缺的一部分,web应用程序的需求越来越大。由于Golang具有高并发性能和简单易用的语言特性,成为了一种越来越流行的web服务器开发语言。那么,如何使用Golang来搭建一个高性能w...
    99+
    2023-05-14
  • 如何用一个printf()调用实现一个web服务器
    这篇文章将为大家详细讲解有关如何用一个printf()调用实现一个web服务器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一...
    99+
    2022-10-19
  • 如何使用Node.js搭建一个静态Web服务器
    这篇文章主要介绍了如何使用Node.js搭建一个静态Web服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用Node.js搭建一个静态Web服务器文章都会有所收获,下...
    99+
    2022-10-19
  • 如何使用Node.js构建一个简单Web服务器
    Node.js是一个用于后端服务的JavaScript运行环境,它允许开发者使用同一种语言编写服务器端和客户端应用程序。与其他后端技术相比,Node.js具有更高的处理能力和更好的可扩展性。在这篇文章中,我们将介绍如何使用Node.js构建...
    99+
    2023-05-14
  • 如何用Vearch搭建一个图片搜索服务功能
    本篇内容介绍了“如何用Vearch搭建一个图片搜索服务功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是图片搜索古时候人们对图片的处理...
    99+
    2023-06-19
  • 如何使用Python实现一个简易版Web服务器
    今天小编给大家分享一下如何使用Python实现一个简易版Web服务器的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、简介我...
    99+
    2023-07-05
  • 腾讯云服务器如何关闭一个端口的项目功能
    1. 查看当前端口状态 在关闭一个端口的项目功能之前,首先需要确认该端口的当前状态。可以通过以下命令查看当前服务器上所有正在监听的端口: netstat -tln 该命令将列出所有正在监听的端口及其对应的服务。找到你想关闭的端口,记录...
    99+
    2023-10-27
    腾讯 端口 功能
  • 聊聊如何使用php swoole来搭建一个高性能的服务器环境
    随着计算机技术的不断发展,现在的服务器框架也变得越来越复杂了,你是否曾经遇到过访问量大、响应速度慢等问题?php swoole是一种新兴的服务器框架,它可以使用PHP语言来构建高性能的网络服务器和客户端。在本文中,我们将介绍关于如何使用ph...
    99+
    2023-05-14
  • 如何使用Python中的协程和异步IO实现一个高性能的网络服务器
    如何使用Python中的协程和异步IO实现一个高性能的网络服务器引言:随着互联网的发展,网络服务器的性能要求也越来越高。传统的同步IO方式往往无法满足高并发的需求,导致服务器响应速度较慢。而采用协程和异步IO的方式可以极大地提升服务器的并发...
    99+
    2023-10-27
    协程 高性能 异步IO
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作