Linux 基础入门操作 第十二章 TINY Web 服务器

1 服务器基础架构

1.1 背景知识

Web 服务器使用 HTTP 协议与客户端(即浏览器)通信,而 HTTP 协议又基于 TCP/IP 协议。因此我们要做的工作就是利用 Linux 系统提供的 TCP 通信接口来实现 HTTP 协议。

而 Linux 为我们提供了哪些网络编程接口呢?没错,就是 socket(套接字),我们会在后面详细介绍该接口的使用方式。
另外我们应该清楚 Linux 的系统 I/O 和文件系统的关系。在 Linux 中,所有 I/O 设备都被看作一个个文件,I/O 设备的输入输出被认做读写文件。网络作为一种 I/O 设备,同样被看作文件,而且是一类特殊的文件,即套接字文件。

我们还要对网络通信协议 TCP/IP 有一个大致的了解,知道 IP 地址和端口的作用。

1.2 客户端和服务器编程模型

客户端-服务器编程模型是一个典型的进程间通信模型。客户端进程和服务器进程通常分处两个不同的主机,如下图所示,客户端发送请求给服务器,服务器从本地资源库中查找需要的资源,然后发送响应给客户端,最后客户端(通常是浏览器)处理这个响应,把结果显示在浏览器上。通信示意图如下图所示:

在这里插入图片描述
这个过程看起来很简单,但是我们需要深入具体的实现细节。我们知道,TCP 是基于连接的,需要先建立连接才能互相通信。在 Linux 中,socket 为我们提供了方便的解决方案。

每一对网络连接称为一个 socket 对,包括两个端点的 socket 地址,表示如下:

(cliaddr : cliport, servaddr : servport

其中,cliaddr 和 cliport 分别是客户端 IP 地址和客户端端口,servaddr 和 servport 分别是服务器 IP 地址和服务器端口。客户端-服务器配对过程如下图所示:

在这里插入图片描述
这对地址和端口唯一确定了连接的双方,在 TCP/IP 协议网络中就能轻松地找到对方。

1.3 HTTP 基础知识

HTTP 是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于 1990 年提出,经过几年的使用与发展,得到不断地完善和扩展。

HTTP 协议的主要特点可概括如下:
1.支持客户/服务器模式。

2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。

3.灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。

4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

5.无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

1.4 URL协议

HTTP URL (URL 是一种特殊类型的 URI,包含了用于查找某个资源的足够的信息)的格式如下:

http://host[":"port][abs_path]

http 表示要通过 HTTP 协议来定位网络资源;host 表示合法的 Internet 主机域名或者 IP 地址;port 指定一个端口号,为空则使用缺省端口 80;abs_path 指定请求资源的 URI;如果 URL 中没有给出 abs_path,那么当它作为请求 URI 时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。

例如:
1)输入:www.guet.edu.cn
浏览器自动转换成:http://www.guet.edu.cn/
2)http:192.168.0.116:8080/index.jsp

1.5 请求

http 请求由三部分组成,分别是:请求行、消息报头、请求正文。

请求行以一个方法符号开头,以空格分开,后面跟着请求的 URI 和协议的版本,格式如下:
Method Request-URI HTTP-Version CRLF

其中 Method 表示请求方法;Request-URI 是一个统一资源标识符;HTTP-Version 表示请求的 HTTP协议版本;CRLF 表示回车和换行(除了作为结尾的 CRLF 外,不允许出现单独的 CR 或 LF 字符)。

1.6 使用 socket 处理请求与响应

熟悉 TCP 协议的朋友们应该很容易理解下面的流程图,socket 通信流程如下图所示:

在这里插入图片描述
服务器调用 socket 函数获取一个 socket,然后调用 bind 函数绑定本机的 IP 地址和端口,再调用 listen函数开启监听,最后调用 accept 函数等待直到有客户端发起连接。

另一方面,客户端调用 socket 函数获取一个 socket,然后调用 connect 函数向指定服务器发起连接请求,当连接成功或出现错误后返回。若连接成功,服务器端的 accept 函数也会成功返回,返回另一个已连接的socket(不是最初调用 socket 函数得到的 socket),该 socket 可以直接用于与客户端通信。而服务器最初的那个 socket 可以继续循环调用 accept 函数,等待下一次连接的到来。

连接成功后,无论是客户端还是服务器,只要向 socket 读写数据就可以实现与对方 socket 的通信。图中 rio_readlineb 和 rio_written 是封装的 I/O 读写函数,与 Linux 系统提供的 read 和 write 作用基本相同,详情可见源代码。客户端关闭连接时会发送一个 EOF 到服务器,服务器读取后关闭连接,进入下一个循环。

这里面用到的所有 Linux 网络编程接口都定义在<sys/socket.h>头文件中。

1.7 CGI 介绍

CGI(Common Gateway Interface) 是 WWW 技术中最重要的技术之一,有着不可替代的重要地位。CGI是外部应用程序(CGI 程序)与 WEB 服务器之间的接口标准,是在 CGI 程序和 Web 服务器之间传递信息的过程。CGI 规范允许 Web 服务器执行外部程序,并将它们的输出发送给 Web 浏览器,CGI 将 Web 的一组简单的静态超媒体文档变成一个完整的新的交互式媒体。

Common Gateway Interface,简称 CGI。在物理上是一段程序,运行在服务器上,提供同客户端 HTML页面的接口。这样说大概还不好理解。那么我们看一个实际例子:现在的个人主页上大部分都有一个留言本。留言本的工作是这样的:先由用户在客户端输入一些信息,如评论之类的东西。接着用户按一下“发布或提交”(到目前为止工作都在客户端),浏览器把这些信息传送到服务器的 CGI 目录下特定的 CGI 程序中,于是 CGI 程序在服务器上按照预定的方法进行处理。在本例中就是把用户提交的信息存入指定的文件中。然后 CGI 程序给客户端发送一个信息,表示请求的任务已经结束。此时用户在浏览器里将看到“留言结束”的字样。整个过程结束。

CGI 处理步骤:
⑴通过 Internet 把用户请求送到 web 服务器。
⑵web 服务器接收用户请求并交给 CGI 程序处理。
⑶CGI 程序把处理结果传送给 web 服务器。
⑷web 服务器把结果送回到用户。

2 开源代码分析

2.1 主程序

int main(int argc, char **argv) 
{int listenfd, connfd;char hostname[MAXLINE], port[MAXLINE];socklen_t clientlen;struct sockaddr_storage clientaddr;/* Check command line args */if (argc != 2) {fprintf(stderr, "usage: %s <port>\n", argv[0]);exit(1);}listenfd = Open_listenfd(argv[1]);while (1) {clientlen = sizeof(clientaddr);connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); //line:netp:tiny:acceptGetnameinfo((SA *) &clientaddr, clientlen, hostname, MAXLINE, port, MAXLINE, 0);printf("Accepted connection from (%s, %s)\n", hostname, port);doit(connfd);                                             //line:netp:tiny:doitClose(connfd);                                            //line:netp:tiny:close}
}

主函数参数需要传入服务器绑定的端口号码,得到这个号码后,调用 Open_listenfd 函数,该函数完成socket、bind、listen 等一系列操作。接着调用 accept 函数等待客户端请求。注意,Accept 是 accept 的包装函数,用来自动处理可能发生的异常,我们只需把它们当成一样的就行了。当 accept 成功返回后,我们拿到了 connected socket descriptor,然后调用 doit 函数处理请求。

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

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

相关文章

RAG优化:python从零实现[吃一堑长一智]循环反馈Feedback

本文将介绍一种有反馈循环机制的RAG系统,让当AI学会"吃一堑长一智",给传统RAG装了个"后悔"系统,让AI能记住哪些回答被用户点赞/拍砖,从此告别金鱼记忆: 每次回答都像在玩roguelike:失败结局会强化下次冒险悄悄把优质问答变成新知识卡牌,实现"以…

基于SpringBoot的名著阅读网站

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

[AI建模] 使用Pinokio本地化部署混元2D到3D AI建模服务

近年来,AI驱动的2D转3D建模技术发展迅猛,而Pinokio作为一个强大的AI模型管理与部署平台,使得在本地部署这些复杂的AI模型变得更加简单高效。本文将介绍如何使用Pinokio在本地部署混元2D到3D AI建模服务,并快速生成带或不带Texture的3D模型。 1. 在Pinokio Discover页面找到…

Qt 导入TagLib库

文章目录 0. 前言和环境介绍1. 下载TagLib2. 下载zlib3. 修改.pro文件4. 测试代码 0. 前言和环境介绍 最近在使用Qt写一个播放器&#xff0c;需要解析mp3文件&#xff0c;于是研究了一下如何导入TagLib库 Qt构建套件:Desktop Qt6.8.2 MinGW64-bit Qt Creator安装目录: D:\bit…

【前端面试题】计算机网络相关

总结面试前端过程可能会问到的计算机网络相关知识点 1.HTTP和HTTPS的区别 &#xff08;1&#xff09;HTTPS HTTP 安全加密 HTTPS 是 HTTP 的 加密版&#xff0c;通过 SSL/TLS 保障数据安全&#xff0c;防止窃听和篡改。 &#xff08;2&#xff09;HTTPS 如何保护数据&…

【RabbitMQ高级特性】消息确认机制、持久化、发送方确认、TTL和死信队列

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【中间件】企业级中间件剖析 一、消息确认机制 消费者确认机制确保消息被正确处理后才从队列中删除。如果消费者处理失败&#xff08;如业务异常或宕机&#xff09;&#xff0c;Broker 会重新投递消息…

调用百度api实现语音识别(python)

该代码实现了一个企业级的语音识别解决方案,通过调用百度语音识别API,实现实时录音识别和对已有音频语音识别功能。 百度智能云:请自行访问百度智能云,开通免费的语音识别功能,获取API_KEY和SECRET_KEY。操作按照百度流程即可,可免费申请。 首先,配置下百度API和描述下错…

Python实现小红书app版爬虫

简介&#xff1a;由于数据需求的日益增大&#xff0c;小红书网页版已经不能满足我们日常工作的需求&#xff0c;为此&#xff0c;小编特地开发了小红书手机版算法&#xff0c;方便大家获取更多的数据&#xff0c;提升工作效率。 手机版接口主要包括&#xff1a;搜素&#xff0…

【AndroidRTC-11】如何理解webrtc的Source、TrackSink

Android-RTC系列软重启&#xff0c;改变以往细读源代码的方式 改为 带上实际问题分析代码。增加实用性&#xff0c;方便形成肌肉记忆。同时不分种类、不分难易程度&#xff0c;在线征集问题切入点。 问题1&#xff1a;如何理解VideoSource、VideoTrack&VideoSink三者的关系…

Windows安装Rust环境(详细教程)

一、 安装mingw64(C语言环境) Rust默认使用的C语言依赖Visual Studio&#xff0c;但该工具占用空间大安装也较为麻烦&#xff0c;可以选用轻便的mingw64包。 1.1 安装地址 (1) 下载地址1-GitHub&#xff1a;Releases niXman/mingw-builds-binaries GitHub (2) 下载地址2-W…

英伟达黄仁勋谈人工智能趋势,首提代理式AI,后续机器人将登场

近日&#xff0c;英伟达 GTC 2025 大会主题演讲中&#xff0c;英伟达 CEO 黄仁勋再次身穿皮衣登场。黄仁勋一上来就提到了 AI 发展的未来&#xff0c;现在我们处于生成式 AI&#xff08;Generative AI&#xff09;阶段&#xff0c;但根据黄仁勋的路线图&#xff0c;我们将迈向一…

LCR 187. 破冰游戏(python3解法)

难度&#xff1a;简单 社团共有 num 位成员参与破冰游戏&#xff0c;编号为 0 ~ num-1。成员们按照编号顺序围绕圆桌而坐。社长抽取一个数字 target&#xff0c;从 0 号成员起开始计数&#xff0c;排在第 target 位的成员离开圆桌&#xff0c;且成员离开后从下一个成员开始计数…

水星(MERCURY)监控初始化的恢复和转码方法

水星(MERCURY)的安防监控恢复了很多&#xff0c;其嵌入式文件系统也一直迭代更新。做为数据恢复从业者每天处理最多的就是恢复数据&#xff0c;但是有的时候业务的需要我们不仅仅恢复出数据&#xff0c;还需要能够转码成通用的MP4类文件并要求画面和声音实现“同步”。 故障存…

基于SpringBoot的实现的客户关系管理系统(CRM)(源码+数据库)

464客户关系管理系统&#xff08;CRM&#xff09;&#xff0c;主要功能如下 【后台功能】 权限管理模块: 包括系统的登录与注册功能 用户管理模块: 基于RBAC的权限模型设计, 实现分配角色的功能功能 客户管理模块: 对客户信息进行新增 修改 删除 查看 联络信息管理模块: 对联络…

关于网络的一点知识(持续更新)

1、IP地址和子网掩码、端口号: IP地址是设备在网络上的地址,相当于一栋房子的门牌号。子网掩码相当于房子所在的街道。同一条街道的房子间是通过街道直通的,主人可以互相拜访。 举个例子,如下图所示。 说明:将两台设备的IP和子网掩码转化为二进制,然后将各自的IP地址和…

Python---数据分析(Pandas八:二维数组DataFrame数据操作一: 数据清洗,数据转换)

一、 数据清洗 1.1、 isnull() 用于检测 DataFrame 中的缺失值&#xff0c;它会返回一个相同形状的布尔型 DataFrame&#xff0c;其中每个元素表示原始 DataFrame 中相应位置的元素是否是缺失 值。 import pandas as pd import numpy as np# 创建一个包含缺失值的 DataFrame …

智能汽车图像及视频处理方案,支持视频星轨拍摄能力

美摄科技作为智能汽车图像及视频处理领域的先行者&#xff0c;正以革新性的技术引领着行业的未来发展。美摄科技智能汽车图像及视频处理方案&#xff0c;一个集高效性、智能化、画质增强于一体的创新解决方案&#xff0c;旨在重塑智能汽车图像画质的新标准&#xff0c;并支持前…

Flask接口开发--GET接口

安装Flask 1.安装命令&#xff1a; pip3 install Flask2.查看Flask版本&#xff1a; pip3 show flask如图我的Flask版本号是2.0.3 项目创建 1、在PyCharm中&#xff0c;我们点击左上方的 file&#xff0c;选择 New Project&#xff0c;创建一个Flask项目。&#xff08;Py…

应用权限组列表

文章目录 使用须知位置相机麦克风通讯录日历运动数据身体传感器图片和视频音乐和音频跨应用关联设备发现和连接剪切板文件夹文件(deprecated) 使用须知 在申请目标权限前&#xff0c;建议开发者先阅读应用权限管控概述-权限组和子权限&#xff0c;了解相关概念&#xff0c;再合…

Python为Word文档添加书签并打包成exe

背景简述 由于一些工作场景&#xff0c;需要从多个Word文档中找到出现的关键词&#xff0c;并阅读关键词的上下文内容。文件可能几十个&#xff0c;手动操作太要命了。所以python尝试处理。 目录 背景简述思路第一步、功能实现结果验证 第二步、打包成exe2-1、基础准备2-2、打…