Linux-C 编程 / 网络 / 超迷你的 web server

一、为生活寻找固定的支撑点

1. 什么是生活的支撑点?

  • 让自己感到些许痛苦,但却会带来实实在在的充实感和成就感的事情。

  • 举个栗子,我的支点是运动、看书、研究技术。

2. 固定的支撑点很重要:

  • 三个固定的要素:时间 / 空间 / 事情。

  • 无论发生什么,无论今天你在什么地方,处于怎样的阶段,有哪些安排,你都坚持做这件事,而且一大早起来,就开始执行。

  • 这是一个很强大的心理暗示:只要拥有这些稳定不变的支撑点,你就有信心和足够的能力去面对许多生活里不稳定的东西,并解决掉它们。

二、Linux-C 编程 / 超迷你的 web server

0. 什么是 web server?

web server 有两个意思:

  1. 一台负责提供网页的主机,它通过 http 协议将网页等数据传给客户端(一般是浏览器);

  2. 一个提供网页的服务器程序,例如 Apache / Nginix / lighttped 等;

1. Tinyhttpd 简介

开源项目 Tinyhttpd ( 6K star / 2.8K fork)

官网:

  • https://sourceforge.net/projects/tinyhttpd/

github mirror:

  • https://github.com/EZLippi/Tinyhttpd

中文注释代码:

  • https://github.com/cbsheng/tinyhttpd

Tinyhttpd 是一个 C 语言编写、极度简陋的 web 服务器,也可以叫 http 服务器。

它的作用仅仅是用于学习 http 协议和 UNIX 系统调用, 不能用于生产环境中。

虽然它没有任何商业价值,但是非常适合用来了解 WEB 服务器的基础知识

我们可以用它作为我们学习 Mpjg-streamer / Nginx/ Lighttpd 等更 复杂和更优秀开源项目的跳板。

2. 编译运行

编译运行:

$ git clone https://github.com/EZLippi/Tinyhttpd
$ cd tinyhttpd-0.1.0
$ make
$ ./httpd 
httpd running on port 4000

用浏览器访问:

点击查看大图

用命令访问:

  1. 使用 netstat 查看 tinyhttpd 的网络状态:

$ netstat -ant | grep 4000
tcp        0      0 0.0.0.0:4000            0.0.0.0:*               LISTEN 
  1. 使用 nc 连接 tinyhttpd,并手动发送 http 请求:

$ nc 127.0.0.1 4000
GET /index.html HTTP/1.1   // 输入 http 请求HTTP/1.0 200 OK            // 接收到 http 响应
Server: es-hacker-httpserver
Content-Type: text/html<HTML>
<TITLE>Index</TITLE>
<BODY>
<H1>This is a simple webserver
</BODY>
</HTML>
  1. 使用 curl 给 tinyhttpd 发送 http 请求:

$ curl localhost:4000/index.html
<HTML>
<TITLE>Index</TITLE>
<BODY>
<H1>This is a simple webserver
</BODY>
</HTML>

使用 wireshark 抓包:

点击查看大图

(1) 浏览器:“请给我 ××× 网页的数据。”

(2) web 服务器:“好的,这就是你要的数据。”

3. 了解一下内部实现

3.1 关于 web server 的入门知识

web server 和 http 协议在整个网络传输中的位置:

点击查看大图

web server 处理请求的步骤:

详细一点的步骤:

点击查看大图
  • 建立连接——接受一个客户端连接;

  • 接收请求——从网络中读取一条 http 请求报文;

  • 处理请求——对请求报文进行解析;

  • 访问资源——访问报文中指定的资源;

  • 构建响应——创建带有正确首部的 http 响应报文;

  • 发送响应——将响应回送给客户端;

什么是 http 报文?

  • http 报文是符合 http 协议的文本数据块;

  • 2 种类型:请求报文和响应报文;

  • 请求/响应报文由以下内容组成:

    • 请求行 或状态码行

    • 头字段

    • 空行

    • 可选的报文主体数据

请求行中的方法字段:

http 协议定义了客户端和服务器之间交互的消息内容和步骤,其基本思路非常简单。

首先,客户端会向服务器发送请求消息请求消息中包含的内容是 "对什么" 和 "进行怎样的操作" 两个部分。

其中 "对什么" 的部分就是 URI (Uniform Resource Identifier,统一资源标识符),一般就是网页或者文件或者程序等,而 "进行怎样的操作" 的部分称为方法,包括:

点击查看大图

3.2 Tinyhttpd 的内部实现

分解 httpd.c:

void accept_request(void *arg) 
void bad_request(int client) 
void cat(int client, FILE *resource) 
void cannot_execute(int client) 
void error_die(const char *sc) 
void execute_cgi(int client, const char *path, 
int get_line(int sock, char *buf, int size) 
void headers(int client, const char *filename) 
void not_found(int client) 
void serve_file(int client, const char *filename) 
int startup(u_short *port) 
void unimplemented(int client) 
int main(void) 

就13 个 函数,和一些宏定义,就没有其他内容了。

程序入口:main()

int main(void)
{int client_sock = -1;pthread_t newthread;// 1. 创建 socket,并且等待连接int server_sock = startup(&port);while (1) {// 2. 接受连接client_sock = accept();// 3. 创建处理线程pthread_create(&newthread , NULL, (void *)accept_request, ...)}
}

创建 socket: startup()

int startup(u_short *port)
{struct sockaddr_in name;// 1. 创建 webserver 端的 sockethttpd = socket(PF_INET, SOCK_STREAM, 0);// 2. 初始化 webserver 的 ip 地址name.sin_family = AF_INET;name.sin_port = htons(*port);name.sin_addr.s_addr = htonl(INADDR_ANY);// 3. 绑定 webserver 的socket 和 ip 地址bind(httpd, (struct sockaddr *)&name, ...);// 4. 开始监听listen(httpd, 5);
}

没什么特别的,就是典型 tcp server 编程:

解析 http 请求报文:accept_request()

这里将会完成 web server 最核心的工作:

  • 读取/解析 http 请求报文,构建响应报文。

void accept_request(void *arg)
{// 1. 提取第一行数据numchars = get_line(client, buf, sizeof(buf));// 2. 从第一行数据中提取出 http 方法// 3. 处理 POST 方法// 4. 处理 GET 方法if (strcasecmp(method, "GET") == 0) {// 4.1 提取 URIwhile (...)query_string++;}// 5. 构建并发送 http 响应报文给客户端serve_file(client, path);
}

构建并发送 http 响应报文给客户端:serve_file()

void serve_file(int client, const char *filename)
{// 1. 打开 URI 指定的资源FILE *resource = fopen(filename, "r");// 2. 发送 响应报文的 header: HTTP/1.0 200 OK...headers(client, filename);// 3. 读取并发送资源给 客户端: fgets() ---> send()cat(client, resource);
}

到此,Tinyhttpd的核心实现就分析完了,更多的细节,请各位自行阅读源码吧~~~

4. 相关参考

  • http 权威指南 / 第1~5章

  • Unix 网络编程 / 第1~5章

  • 网络是怎么连接的 / 第1、2、6章

  • 深入理解 Nginx 模块;

  • Lighttpd Documentation (https://redmine.lighttpd.net/projects/lighttpd/wiki/docs)

三、思考技术,也思考人生

要学习技术,更要学习如何生活

你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20165326 java第四周学习笔记

第四周学习笔记 ch5 子类和父类子类只能有一个父类使用关键字extendsyclass 子类 extends 父类系统默认的祖先类Object&#xff08;java.lang包中&#xff09;继承&#xff1a;子类继承父类的方法可以直接作为实例方法调用&#xff0c;继承的成员变量和方法的访问权限不变&…

用VSTS进行网站压力测试

VSTS提供了一个丰富、强大的工具平台&#xff0c;融合了软件开发领域的各个角色&#xff0c;涵盖软件开发生命周期的各个阶段&#xff0c;包括设计&#xff0c;开发&#xff0c;测试&#xff0c;管理&#xff0c;而这一整套构件的融会贯通&#xff0c;让它可以有效地改善软件开…

第四周选做作业

相关知识点的总结 通过命令行引入参数递归循环课上内容的补做&#xff0c;结果截图 未完成内容:递归与循环 补做教材第二章&#xff0c;第三章编程题目 参考资料 2016-2017-2 《Java 程序设计》课堂实践项目编写一个Java应用程序,输出全部的希腊字母。_百度知道[]转载于:https:…

数据结构和算法,也就那么回事儿

金三银四来了&#xff0c;各大厂动静不小&#xff0c;都在储备人才&#xff0c;绝对是程序员面试的黄金时间了&#xff0c;不少同学也在后台反馈面试中遇到的一些问题&#xff0c;所以今天想跟大家说说算法。说起算法&#xff0c;那大厂面试是绝对必考的&#xff0c;可以说是一…

SecureCRT护眼设置

SecureCRT护眼设置Option —— Global Options —— Terminal —— Appearance —— ANSI COlor从左至右&#xff0c;从上至下值分别为&#xff08;RGB元组&#xff09;&#xff1a; 1&#xff1a;(0,43,53) (128,128,0) (0,160,0) (160,160,0) (255,128,128) (…

北美暴风雨,Linux5.12被延迟6天发布

上个月中旬&#xff0c;因为罕见的严寒天气和暴风雪&#xff0c;美国得州和俄勒冈州波特兰遭遇了持续多天的停电。Linux 创始人 Linus Torvalds 就生活在波特兰&#xff0c;多年来他一直在家中远程工作&#xff0c;并负责新内核的最终发布。之前我们报道过&#xff0c;内核社区…

C#复习笔记(3)--C#2:解决C#1的问题(可空值类型)

可空值类型 C#2推出可空类型来表示可以为null的值类型。这是一个呼声很高的需求&#xff0c;因为在常用的数据库中都是允许某些值类型可为空的。那么为什么值类型就不能为空呢&#xff1f;内存中用一个全0的值来表示null&#xff0c;但是全0的地址说明了这个内存空间是被清除了…

ISA之三种客户端访问

我们已经懂得怎么搭建ISA2006.我们今天来利用ISA访问外网&#xff01;顺便说声如果你IP&#xff0c;网关&#xff0c;DNS什么都没问题。那么你可以看看你的NAT处理&#xff01;下面我们看看我们的试验拓扑&#xff01;我们在ISA的服务器上做访问规则&#xff01;来允许我们可以…

面试官不讲武德,居然让我讲讲蠕虫和金丝雀!

1. 蠕虫病毒简介2. 缓冲区溢出3. 缓冲区溢出举例4. 缓冲区溢出的危害5. 内存在计算机中的排布方式6. 计算机中越界访问的后果7. 避免缓冲区溢出的三种方法7.1 栈随机化7.2 检测栈是否被破坏7.3 限制可执行代码区域8. 总结蠕虫病毒是一种常见的利用Unix系统中的缺点来进行攻击的…

asp.net core 拦击器制作的权限管理系统DEMO

效果图 没有登陆不会执行请求日期的方法&#xff0c;不管是否登陆都不允许访问请求时间方法 验证不通过是会进行转发到Home/error方法中&#xff0c; 代码附上&#xff1a; [Route("[controller]/[action]")]public class HomeController : BaseController{/// <s…

工程师姓什么很重要!别再叫我“X工”!!!

工程师之间都是这么互相打招呼的——“高工&#xff0c;你设计图通过了么&#xff1f;”“李工&#xff0c;工程画完了吗&#xff1f;”“王工&#xff0c;你真是越来越漂亮了&#xff01;”"张工&#xff0c;你的DFM整完了吗"“周公&#xff0c;Schedule 该更新了”…

说一下NFC,手机有NFC功能却不能模拟门禁卡?

img1、NFC是什么&#xff1f;NFC&#xff08;Near Field Communication&#xff09; 技术由Philips、Nokia和Sony主推的一种近距离无线通信技术&#xff08;NFCIP-1&#xff09;&#xff0c;是一种短距离非接触式的通信方式&#xff0c;通常有效通讯距离为4厘米以内。工作频率为…

小程序员的大梦想 与盖茨像哥们儿

小程序员的大梦想 与盖茨像哥们儿以10亿的天价转会新华都&#xff0c;让唐骏有机会开创其职业经理人生涯的新局面&#xff0c;但在此之前&#xff0c;他的成功已得到证明面前的唐骏温和得令人吃惊。仿佛“前微软中国区总裁”、“打工皇帝”、“10亿转会身价”这样的光环带给他的…

动态规划详解

个人见解&#xff1a;1.动态规划实现了把问题拆分成多个子问题&#xff0c;然后求解&#xff0c;子问题有解后&#xff0c;问题自然迎刃而解&#xff1b;2.动态规划实现了子问题的状态的迁移&#xff0c;保存每个状态值&#xff0c;递推出答案&#xff0c;但不记录每种状态的求…

我的奶奶

突然想起我奶奶&#xff0c;是突然发现&#xff0c;距离奶奶去世已经有快十年&#xff0c;这十年时间&#xff0c;我也再也没有见过奶奶。奶奶刚去世的前几年&#xff0c;有时候会梦到奶奶跟我说话&#xff0c;她总是会很耐心的告诉我很多道理。奶奶从小到大都没有指责过我&…

WPF应用程序内存泄漏的一些原因

原文&#xff1a;Finding Memory Leaks in WPF-based applications There are numbers of blogs that folks wrote about memory leaks in Microsoft .Net Framework managed code and unmanaged code based applications. In this blog I wanted to: Show coding practices th…

[转]Eclipse RCP应用系统开发方法与实战2-- 定制应用程序窗口属性

5.1.4 定制应用程序窗口属性 向导生成的应用程序主界面并不能满足要求&#xff0c;存在很多问题&#xff0c;例如&#xff0c;主界面运行时没有自动居中&#xff0c;主界面大小没有固 定&#xff0c;主窗口标题栏文字应该是“高校经费测算系统”。再看看图5-3、图5-4的标题栏有…

赢在中国 - 史玉柱经典语录

1.要重视建立销售手册2.凡是先做试点&#xff0c;风险才低。3.找到自己的细分市场。4.不要总想着同竞争对手对立&#xff0c;而是要想办法让自己弥补竞争对手的不足。5. 如果没有价格上的优势与技术上的绝对优势&#xff0c;千万不要进入红海市场&#xff0c;否则你会必输无疑&…

我最近在学微信小程序开发,一起吗?

从当初的一夜成名&#xff0c;到今天火爆的市场占有率&#xff0c;微信小程序已走过 4 个年头。据今年 1 月阿拉丁发布的报告显示&#xff0c;微信小程序 2020 年 DAU 已破 4 亿&#xff0c;其总数超 380 万。最近有读者问我说&#xff0c;发哥&#xff0c;之前自己一直是个人…

WebService大讲堂之Axis2(2):复合类型数据的传递

在实际的应用中&#xff0c;不仅需要使用WebService来传递简单类型的数据&#xff0c;有时也需要传递更复杂的数据&#xff0c;这些数据可以被称为复合类型的数据。数组与类&#xff08;接口&#xff09;是比较常用的复合类型。在Axis2中可以直接使用将WebService方法的参数或返…