返回顶部
首页 > 资讯 > 服务器 >怎么用C写一个web服务器之基础功能
  • 184
分享到

怎么用C写一个web服务器之基础功能

2023-06-15 05:06:26 184人浏览 独家记忆
摘要

这篇文章给大家分享的是有关怎么用C写一个WEB服务器之基础功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。服务器架构目标架构以 Nginx 的思想来考虑本服务器架构,初步考虑如下图:当然 PHP 进程也可以替换

这篇文章给大家分享的是有关怎么用C写一个WEB服务器之基础功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

服务器架构

目标架构

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

怎么用C写一个web服务器之基础功能

当然 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 请求中客户端与服务器之间的交互:

怎么用C写一个web服务器之基础功能

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

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

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

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

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

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

调用 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服务器之基础功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

--结束END--

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

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

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

猜你喜欢
  • 怎么用C写一个web服务器之基础功能
    这篇文章给大家分享的是有关怎么用C写一个web服务器之基础功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。服务器架构目标架构以 nginx 的思想来考虑本服务器架构,初步考虑如下图:当然 php 进程也可以替换...
    99+
    2023-06-15
  • 如何用C写一个web服务器之基础功能
    目录服务器架构目标架构当前状态功能实现socket系列方法服务器与 PHP cli 交互报文数据处理服务器架构 目标架构 以 nginx 的思想来考虑本服务器架构,初步考虑如下图: ...
    99+
    2024-04-02
  • 怎么用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
  • 如何用C写一个web服务器之CGI协议
    目录前言CGICGI请求CGI响应Nginx和PHP的CGI实现SAPIPHP-FPM纠偏代码实现http_parsercJSON前言 这次更新主要实现一下 CGI 协议。 先放上G...
    99+
    2024-04-02
  • 如何用C写一个web服务器之GCC项目编译
    目录前言编译步骤静态库和动态库静态库动态库CMakeLists前言 本想着接下来大概实现一下 CGI 协议,但是实现过程中被一个问题卡住了: C进程与php进程的交互数据类型问题: ...
    99+
    2024-04-02
  • 如何用C写一个web服务器之I/O多路复用
    目录前言I/O模型select/poll/epollepoll介绍epoll_createepoll_ctlepoll_waitepoll行为代码实现整体处理逻辑设置epoll ET...
    99+
    2024-04-02
  • C#怎么实现Web服务器功能
    这篇文章主要讲解了“C#怎么实现Web服务器功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#怎么实现Web服务器功能”吧!C#实现Web服务器功能的程序设计根据HTTP协议的作用原理,...
    99+
    2023-06-17
  • 基于C++怎么编写一个简单的服务器
    这篇文章主要讲解了“基于C++怎么编写一个简单的服务器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于C++怎么编写一个简单的服务器”吧!先写个简易的controller基类继承反射基类,...
    99+
    2023-07-05
  • 基于C++编写一个简单的服务器
    本文使用上一期写的反射类,另外我发现<WinSock2.h>这个头文件里有RegisterClass 这个结构,还有typedef RegisterClass Regis...
    99+
    2023-03-14
    C++编写简易服务器 C++编写服务器 C++服务器
  • 基于C++怎么编写一个Json解析器
    这篇文章主要介绍了基于C++怎么编写一个Json解析器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇基于C++怎么编写一个Json解析器文章都会有所收获,下面我们一起来看看吧。代码JsonSerialize.h...
    99+
    2023-07-05
  • 利用JavaScript怎么编写一个换肤功能
    这篇文章给大家介绍利用JavaScript怎么编写一个换肤功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。原理通过点击事件,获取点击的的图片的信息,在HTML背景图片的路径改变css样式<style>&n...
    99+
    2023-06-06
  • C#中怎么创建一个Web Service服务
    本篇文章为大家展示了C#中怎么创建一个Web Service服务,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。为什么需要Web Service以前,分布式的应用程序逻辑需要使用分布式的对象模型,通过...
    99+
    2023-06-18
  • 利用Java怎么编写一个倒计时功能
    利用Java怎么编写一个倒计时功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1.简易方式实现 import java.util.*; import java...
    99+
    2023-05-31
    java ava
  • 使用jQuery怎么编写一个评论区功能
    本篇文章给大家分享的是有关使用jQuery怎么编写一个评论区功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。首先我们用html和css来进行编写这样一个区域:html内容:&...
    99+
    2023-06-07
  • 怎么用C++编写一个Json解析器
    今天小编给大家分享一下怎么用C++编写一个Json解析器的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。之前用RapidJso...
    99+
    2023-07-05
  • 使用django怎么编写一个单元测试功能
    本篇文章给大家分享的是有关使用django怎么编写一个单元测试功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、使用requests模拟Http请求   假设你执行成功的返...
    99+
    2023-06-14
  • 使用PHP怎么编写一个在线聊天功能
    这期内容当中小编将会给大家带来有关使用PHP怎么编写一个在线聊天功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。php有什么用php是一个嵌套的缩写名称,是英文超级文本预处理语言,它的语法混合了C、Ja...
    99+
    2023-06-14
  • 怎么用PHP编写一个修改多个用户密码的功能
    本篇内容主要讲解“怎么用PHP编写一个修改多个用户密码的功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用PHP编写一个修改多个用户密码的功能”吧!一、数据库设计在编写前,我们需要先设计数...
    99+
    2023-07-05
  • C++中怎么利用Doxygen实现一个分享功能
    这篇文章给大家介绍C++中怎么利用Doxygen实现一个分享功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。用C++ Doxygen进行可自动文档化的代码注释,可从代码中提取注释生成帮助文档。在使用Doxygen时将...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作