web服务器

https://tool.oschina.net/
http协议默认端口是 80
https默认端口     443
// 客户端 -> 浏览器
	-> 发送请求给服务器 -> 地址栏/通过链接
	-> 地址栏发送请求细节:
		https://www.baidu.com/:9999
			- htts: 协议
			- baidu.com: 域名
				- 域名的作用: 方便记忆, 连接服务器的时候使用的IP地址不是域名
				- 域名需要和IP地址绑定
					- 通过域名访问web服务器
					- 当前主机会连接dns服务器 -> 得到域名对应的IP地址
					- 得到IP之后通过IP访问服务器
			- 9999: 访问的服务器绑定的端口是9999
					

1. HTML

1.1 html简介

超文本标记语言(Hyper Text Markup Language),标准通用标记语言下的一个应用。HTML 不是一种编程语言,而是一种标记语言 (markup language),是网页制作所必备的。

超文本就是指页面内可以包含图片、链接,甚至音乐、程序等非文字元素。

超文本标记语言的结构包括**“**头”部分(英语:Head)、和“主体”部分(英语:Body),其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。

  • html 特点

    • 语法非常简洁、比较松散,以相应的英语单词关键字进行组合

      • 使用了很多标签, 每个标签都有固定的意思
      • 使用的标签一般都是成对的, 也有特殊的单标签
    • html标签不区分大小写

    • 大多数标签是成对出现的, 有开始, 有结束

    • 不成对出现的称之为短标签

  • html文件命名

    • xxxx.html
    • xxx.htm
  • 注释

    <!--  我是一个html注释  -->
    <!-- xxxxxx  -->
    <html></html>
    <img>
    
    <!-- 一般格式  -->
    <html>
        <head></head>
        <body></body>
    </html>
    

1.2 文字和标题标签

<!--  标题标签, 一共有6个, 数字越大, 显示的字体越小  -->
<h1></h1>
<h2></h2>
<h3></h3>
......
<h6></h6>

<!--  文字  -->
<font color="blue" size="5">hello,world</font>
属性: 
	color: 文字颜色
		□ 表示方式:
			® 英文单词: red green blue......
			® 使用16进制的形式表示颜色: #ffffff
	
	size: 文字大小
		□  范围 1 -- 7
			® 1最小, 7最大	
<!-- 段落 自动换行 -->
<p></p>

<!-- 换行 单标签, 末尾有没有/都可以 -->
<br/>  or <br>

<!-- 水平线 单标签, 末尾有没有/都可以 -->
<hr/>  or <hr>

<!--  文本格式  -->
加粗:
	<strong></strong> 
	<b></b> 

文本倾斜标签 
	<em></em> 
	<i></i> 

删除线标签 
	<del></del> 
	<s></s> 

下划线标签
	<ins></ins> 
	<u></u> 

1.3 列表标签

1. 无序列表 - unorderered list
	○ 标签
        <ul type="">
            <li></li>
            <li></li>
        </ul>
    ○ 属性: type
        § 实心圆圈: disc -> 默认
        § 空心圆圈: circle
        § 小方块: square

2. 有序列表 -> orderered
    ○ 标签
        <ol type="">
            <li></li>  列表项
            <li></li>
        </ol>
	○ 属性: 
        ○ type -- 序号
            □ 1 
            □ a
            □ A
            □ i 	-> 罗马字母
            □ I  

3. 自定义列表
    ○ 标签
        <dl>
            <dt></dt> 		-> 大标题
            	<dd></dd> 	-> 小标题
            	<dd></dd> 
        </dl>
显示的数据格式:
第一章
	1.1 xxx
	1.2 xxx
第二章
	2.1 xxx
	2.2 xxx

1.4 图片标签 -> 单标签

<img>  <img/>
<img src="3.gif" alt="小岳岳" title="我的天呐!" width="300" height="200" />
	○ 属性: 
		§ src: 图片的来源 必写属性
			- 网络地址: http://xxxxx
			- 本地地址: 
				- 使用相对路径
				- 使用绝对路径
		§ alt: 替换文本 图片不显示的时候显示的文字
		§ title: 提示文本 鼠标放到图片上显示的文字
		§ width: 图片宽度
		§ height: 图片高度
	○ 注意:
		§ 如果只更改图片的宽度或者高度,图片等比例缩放。

1.5 超链接标签

<a href="http://jd.com" title="A dog" target="_blank">超链接</a>
	○ 属性:
		○ href: 去往的路径(跳转的页面)必写属性
		○ title: 提示文本, 鼠标放到链接上显示的文字
		○ target
			□ _self:   默认值 在自身页面打开(关闭自身页面,打开链接页面)
			□ _blank: 打开新页面 (自身页面不关闭,打开一个新的链接页面)

1.6 表格标签

<table>
    <tr>
        <td></td>  第一列
        <td></td>  第二列
    </tr>
    <tr>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td></td>
    </tr>
</table>

属性设置:
	○ <table></table>
		§ 属性:
			□ border -- 表格线, 宽度1-7
			□ bordercolor -- 表格线颜色
			□ width
			□ height 
	○ <tr> -- 行 
		§ 属性
			□ align -- 对齐方式
				® center
				® left
				® right
	○ <td> -- 单元格(列)
		§ 对其属性设置同tr

2. HTTP协议

osi四层模型:
应用层
	- http协议
传输层
	- tcp
	- udp
网络层
	- ip
网络接口层(物理层)
    
协议是什么?
	- 数据的组织格式

网络通信:(B/S) -> 数据格式使用是http
	- 客户端
		浏览器
	- 服务器端
		后台程序
// 网络通信
客户端:
	- 发起请求
		- 不管使用什么类型的浏览器, 发送的请求的格式必须是相同的
		- http请求协议 (请求数据的格式)
	- 接收服务器回复的信息
		- 需要根据http响应协议就接收的数据进行解析
			- 得到了服务器回复的原始数据
服务器:
	- 接收客户端请求
		- 接收http请求协议, 按照数据格式, 解析出具体的数据
	- 处理并且给客户端回复数据
		- 回复的数据的格式是固定的
		- http响应协议, 根据这个协议组织回复数据

2.1 http请求

// 请求协议数据:
	- 在客户端组织发送给服务器
	- 服务器端接收请求协议信息, 并解析
	
// http请求分为两大类
	- get请求
	- post请求
	
// http协议在组织数据的时候有很多行, 换行的时候使用的是\r\n

四部分: 请求行, 请求头, 空行, 请求数据

  • 请求行: 说明请求类型, 要访问的资源, 以及使用的http版本
  • 请求头: 说明服务器要使用的附加信息
  • 空行: 空行是必须要有的, 即使没有请求数据
  • 请求数据: 也叫主体, 可以添加任意的其他数据
    • 向服务器提交的数据
  • Get方式提交数据

    # 下边的http请求的数据块是谁组织的?
    	- 浏览器组织的, 安照http请求协议组织数据
    # 基于get的http请求
    # 第一部分: 请求行, 第一行
    	- GET: 提交数据的方式
    	- /?username=subwen%40qq.com&phone=11223344&email=11%40aa.com&date=2019-01-01&sex=male&class=3&rule=on
    		- /: 代表要访问的服务器路径 == 资源根目录(服务器提供的存储资源的目录, 数据是给客户端访问的)
    			- /hello/: 资源根目录中 的hello子目录
      			- /hello/a.html: 资源根目录中 的hello子目录中的a.html文件
    		- ?后边的字符串代表客户端向服务器提交的额外的数据
    	- HTTP/1.1: http协议 的版本
    	
    # 第二部分: 请求头(若干行, 都是键值对 key:value), 第2-8行
    # 第三部分: 空行, 第9行
    # 第四部分: 请求数据(提交的数据)
    	- 在请求行的第二部分, ?后边的字符串
    
    GET /?username=subwen%40qq.com&phone=11223344&email=11%40aa.com&date=2019-01-01&sex=male&class=3&rule=on HTTP/1.1
    

Host: 192.168.16.49:6789
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh,zh-CN;q=0.9,en;q=0.8


- `User-Agent`: 用户使用的浏览器类型

- Post方式提交数据

```shell
# 第一部分: 请求行, 第一行
	- POST: 客户端向服务器提交数据的方式
	- /: 服务器提供的资源根目录
	- HTTP/1.1: http协议的版本
	
# 第二部分: 请求头(键值对, 若干个), 第2-12行
# 第三部分: 空行(不能省略), 第13行
# 第四部分: 请求数据(给服务器提交的数据), 第14行
POST / HTTP/1.1
Host: 192.168.16.49:6789
Connection: keep-alive
Content-Length: 98
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh,zh-CN;q=0.9,en;q=0.8

username=subwen%40qq.com&phone=11223344&email=11%40aa.com&date=2019-01-01&sex=male&class=3&rule=on
  • 请求头

    Content-Type: 客户端向服务器提交的数据的数据格式
    Content-Length: 客户端向服务器提交的数据的长度, 这个长度必须要准确, 如果不知道有多长, 指定为 -1
    
  • http中的get和post的区别

    • get
      • 提交的数据会显示到浏览器的地址栏中
        • 敏感信息会泄露
        • 浏览器的地址栏显示数据是需要缓存的, 不同 的浏览器提供的缓存大小不同
          • 缓存都不会太大, 级别就是 几k 左右
          • 发送大数据会部分丢失
      • 适合于向服务器获取静态资源
        • 图片
        • 网页
      • 向服务器提交一些不敏感的少量的属于也可以
    • post
      • 提交大数据
        • 1G ↑
      • 提交的数据不会显示到地址栏中

2.2 http响应

响应消息(Response) -> 服务器给客户端发送的数据

  • 四部分: 状态行, 消息报头/响应头, 空行, 响应正文(服务器回复给客户端的数据)
    • 状态行: 包括http协议版本号, 状态码, 状态信息
      • HTTP/1.1 200 Ok
    • 消息报头: 说明客户端要使用的一些附加信息
      • 服务器准备好的, 要发送给客户端使用的信息
    • 空行: 空行是必须要有的
    • 响应正文: 服务器返回给客户端的文本信息
# 第一部分: 状态行, 第一行
	- HTTP/1.1: http协议的版本
	- 200: 状态码
	- OK: 状态描述
	
# 第二部分: 消息报头(响应头), 键值对, 第2-11行
	- Content-Type: 描述的是给客户端回复的数据(响应数据)的格式
	- Content-Length: 给客户端回复的数据(响应数据)的长度
# 第三部分: 空行(必须得有), 第12行
# 第四部分: 响应数据 -> 服务器回复给客户端的数据(空行下边的所有内容)
HTTP/1.1 200 Ok
Server: micro_httpd
Date: Fri, 18 Jul 2014 14:34:26 GMT
/* 告诉浏览器发送的数据是什么类型 */
Content-Type: text/plain; charset=iso-8859-1 (必选项) 西欧编码->不支持中文 , utf8支持中文
/* 发送的数据的长度 */
Content-Length: 32  
Location: https://www.biadu.com
Content-Language: zh-CN
Last-Modified: Fri, 18 Jul 2014 08:36:36 GMT
Connection: close

#include <stdio.h>
int main(void)
{
    printf("hello world!\n");
    return 0;
}
  1. http状态码

    状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

    • 1xx:指示信息–表示请求已接收,继续处理
    • 2xx:成功–表示请求已被成功接收、理解、接受
    • 3xx:重定向–要完成请求必须进行更进一步的操作
    • 4xx:客户端错误–请求有语法错误或请求无法实现
    • 5xx:服务器端错误–服务器未能实现合法的请求

    常见状态码:

    • 200 OK 客户端请求成功
    • 400 Bad Request 客户端请求有语法错误,不能被服务器所理解
    • 401 Unauthorized 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
    • 403 Forbidden 服务器收到请求,但是拒绝提供服务
    • 404 Not Found 请求资源不存在,eg:输入了错误的URL
    • 500 Internal Server Error 服务器发生不可预期的错误
    • 503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

3. web服务端实现

// 每个函数<100行代码 -> 每个函数的功能单一
// 使用epoll实现 -> 边沿非阻塞
// 入口函数
// 服务器程序
// tcp服务器 -> epoll

// 初始化监听的套接字
int initListen()
{
    int lfd = socket();
    bind();
    listen();
    return lfd;
}

// 接受新连接, 添加到epoll树
void acceptConn(int lfd, int epfd)
{
    int cfd = accept(lfd);
    // 添加到epoll树
    epoll_ctl(epfd, );
}

// 解析http请求
void parseHttpRequest()
{
    
}

// http响应

// 接收数据
void recvHttpRequest()
{
    revc/read();
    // 得到的数据 http请求格式 -> 根据http请求协议解析
    // 解析操作
    parseHttpRequest();
}

// 创建并启动epoll模型
void runEpoll(int lfd)
{
    int epfd = epoll_create();
    // 添加监听的套接字到epoll树
    epoll_ctl();
    // 启动epoll模型
   	while(1)
    {
        struct epoll_event evs[1024];
        int num = epoll_wait(epfd, evs, max, -1);
        for(int i=0; i<num; ++i)
        {
            int curfd = evs[i].data.fd;
            // 新连接
            if(curfd == lfd)
            {
                // 接受连接, 并将通信的fd添加到树上
                acceptConn(lfd, epfd);
            }
            // 通信
            else
            {
                // 接收客户端数据 -> http请求消息
            }
        }
    }
}

// 等待并接受连接

int main()
{
    // 主流程
    // 启动服务器
    int lfd = initListen();
    runEpoll(lfd);
}

4. 相关操作函数

  • sscanf函数

    // 函数原型
    // 将参数str的字符串根据参数format字符串来转换并格式化数据,转换后的结果存于对应的参数内。
    sscanf(const char *str, const char *format, ...)。
    
    具体功能如下:
    (1)根据格式从字符串中提取数据。如从字符串中取出整数、浮点数和字符串等。
    (2)取指定长度的字符串
    (3)取到指定字符为止的字符串
    (4)取仅包含指定字符集的字符串
    (5)取到指定字符集为止的字符串
    
    sscanf可以支持格式字符%[](1)-: 表示范围,如:%[1-9]表示只读取1-9这几个数字 %[a-z]表示只读取a-z小写字母,类似地 %[A-Z]只读取大写字母
    (2)^: 表示不取,如:%[^1]表示读取除'1'以外的所有字符 %[^/]表示除/以外的所有字符
    (3),: 范围可以用","相连接 如%[1-9,a-z]表示同时取1-9数字和a-z小写字母 
    (4)原则:从第一个在指定范围内的数字开始读取,到第一个不在范围内的数字结束%s 可以看成%[] 的一个特例 %[^ ](注意^后面有一个空格!)
    
    const char *s = "http://www.baidu.com:1234";
    char protocol[32] = { 0 };
    char host[128] = { 0 };
    char port[8] = { 0 };
    sscanf(s,"%[^:]://%[^:]:%[1-9]",protocol,host,port);
    
    printf("protocol: %s\n",protocol);
    printf("host: %s\n",host);
    printf("port: %s\n",port);
    
    ///
    sscanf("123456 abcdedf", "%[^ ]", buf);
    printf("%s\n", buf);
    结果为:123456
    ///
    sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
    printf("%s\n", buf);
    结果为:123456abcdedf
    ///
    sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
    printf("%s\n", buf);
    结果为:123456abcdedf
    
    
  • scandir函数

    // 头文件
    #include <dirent.h> 
    //函数定义
    /*
    	函数scandir扫描dir目录下以及dir子目录下满足filter过滤模式的文件,返回的结果是compare函数经过排 
    	序的,并保存在 namelist中。注意namelist是通过malloc动态分配内存的,所以在使用时要注意释放内存。
    	alphasort和versionsort 是使用到的两种排序的函数。 
    	当函数成功执行时返回找到匹配模式文件的个数,如果失败将返回-1。
    */
    int scandir(const char *dir,struct dirent **namelist,int (*filter)(const void *b),
                      int (* compare)(const struct dirent **, const struct dirent **));
    int alphasort(const void *a, const void *b);
    int versionsort(const void *a, const void *b);
    

5. 转码

url在数据传输过程中不支持中文,需要转码。

  • 汉字

  • 特殊字符

    • 查看manpage
    • man ascii
    • 要处理可见字符
    • 从space开始 - 32
      • 前0-31个不可见
  • 不需要转换的特殊字符

      • .
      • _
    • /
  • ~

    • 0-9
    • a-z
    • A-Z
  • 需要转换的字符使用其16进制的值前加%表示

在vs中创建linux项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KaXkM5Mu-1617159057084)(assets/1570440056235.png)]

的个数,如果失败将返回-1。
*/
int scandir(const char *dir,struct dirent **namelist,int (*filter)(const void b),
int (
compare)(const struct dirent **, const struct dirent **));
int alphasort(const void *a, const void *b);
int versionsort(const void *a, const void *b);




# 5. 转码

> url在数据传输过程中不支持中文,需要转码。
>
> - 汉字
>
> - 特殊字符
>
> - - 查看manpage
>- - man ascii
>   - 要处理可见字符
>- - 从space开始 - 32
>     - 前0-31个不可见
>- 不需要转换的特殊字符
>   - - .
>     - _
>  - *
>     - /
>  - ~
>     - 0-9
>     - a-z
>     - A-Z
>   - 需要转换的字符使用其16进制的值前加%表示